GO微服务
·
微服务
RPC
- 远程过程调用,一个服务去调用另一个服务的方法
遇到的问题
- CALL id的映射
- 序列化和反序列化
- 网络传输
GO内置rpc
- 服务端
type HelloService struct {
}
func (this *HelloService) SayHello(req string, reply *string) error {
*reply = "hello"
return nil
}
func main() {
//实列化要给server
listen, err := net.Listen("tcp", "localhost:1234")
if err != nil {
fmt.Println("Listen err:", err.Error())
}
//注册处理逻辑
_ = rpc.RegisterName("HelloService", &HelloService{})
//启动服务
accept, _ := listen.Accept()
rpc.ServeConn(accept)
}
- 客户端
func main() {
client, err := rpc.Dial("tcp", "localhost:1234")
if err != nil {
fmt.Println("Dial err:", err.Error())
}
var reply string
err = client.Call("HelloService.SayHello", "suncc", &reply)
fmt.Println(reply)
if err != nil {
fmt.Println(err)
}
}
GRPC
- grpc 谷歌的
- protobuf 就是高压缩比
- 序列化和反序列快
- 传输速度快
- 简单使用
- 维护成本低
- 向后兼容
- 加密性好
安装
- 要去下载protoc
- 然后执行go get 命令
protobuf
- 基本格式
//使用proto3的语法
syntax = "proto3";
//.表示生成的go文件在那个目录下
//serivce 表示生成的go的包名
option go_package=".;service";
//定义一个rpc服务接口
service SayHello {
rpc SayHello(HelloRequest) returns (HelloReply);
rpc BayHello(HelloRequest) returns (HelloReply);
}
message Person {
string name = 1;
int32 age = 2;
repeated string hobbies = 3;//代表是切片
}
message HelloRequest {
string name = 1;//消息的编号
repeated string hobbies = 2;//代表是切片
Person person = 3;
}
message HelloReply {
string msg = 1;
}
// protoc --go_out=. hello.proto
// protoc --go-grpc_out=. hello.proto
grpc的使用
- 客户端
package main
import (
service "RPC/helloword/hello-server/proto"
"context"
"fmt"
"google.golang.org/grpc"
"net"
)
type server struct {
service.UnimplementedSayHelloServer //提供默认实现
}
//固定写法
func (srv *server) SayHello(ctx context.Context, in *service.HelloRequest) (*service.HelloReply, error) {
return &service.HelloReply{Msg: "nihao"}, nil
}
func (srv *server) SayBye(ctx context.Context, in *service.HelloRequest) (*service.HelloReply, error) {
return &service.HelloReply{Msg: "byebye"}, nil
}
func main() {
g := grpc.NewServer()
service.RegisterSayHelloServer(g, &server{})
listen, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println("failed to listen: %v", err)
return
}
err = g.Serve(listen)
if err != nil {
fmt.Println("failed to serve: %v", err)
return
}
}
- client
dial, err := grpc.Dial("localhost:8080", grpc.WithInsecure())
if err != nil {
return
}
defer dial.Close()
client := service.NewSayHelloClient(dial)
hello, err := client.SayHello(context.Background(), &service.HelloRequest{Name: "world"})
if err != nil {
return
}
fmt.Println(hello)
grpc 模式
- 简单模式
- 服务端数据流模式
- 客户端数据流
- 双向数据流
https://blog.csdn.net/weixin_54984185/article/details/135378670
Protobuf
bool → bool
int32 → int32
int64 → int64
uint32 → uint32
uint64 → uint64
sint32 → int32(带符号的可变长度编码)
sint64 → int64(带符号的可变长度编码)
fixed32 → uint32(固定 4 字节)
fixed64 → uint64(固定 8 字节)
sfixed32 → int32(固定 4 字节带符号)
sfixed64 → int64(固定 8 字节带符号)
float → float32
double → float64
string → string(必须是 UTF-8 编码)
bytes → []byte
option
option go_package = “.;proto”
option java_package
“生成目录位置;包名”
protobuf中使用其他的message
-Base.proto
- import “base.proto”
//使用谷歌自带的message
import "google/protobuf/empty.proto";
rpc Test (google.protobuf.Empty) returns (google.protobuf.Empty) {}
message 嵌套
- 如果直接加入message 那就是会提升
message Result{
string name
int age
}
message Hello{
Result value //这个内容是会被提升的
//变成??
string name??
int age??
}
//使用的时候
Hello_Result{} 这个方式来初始化
枚举类型
enum Gender{
MALE = 0;
FEMALE = 1;
}
message User{
Gender g = 2
}
如果要使用 Gender_FEMALE
map类型
message User{
map<string,string> hooby
}
使用timestamp
import "google/protobuf/timestamp.proto";
google.protobuf.Timestamp timestamp = 2;
grpc的metadata
- 比较重要
grpc验证器
- 就相当于表单验证
- protoc-gen-validate
- 将下载exe放到bin的目录下
- 使用 https://blog.csdn.net/weixin_50448879/article/details/136629547
grpc中的异常处理
- status.New(codes.NotFound,“记录未找到”)
grpc客户端超时机制
- context.WithTimeout(context.Background(),time.Second*3)
更多推荐
所有评论(0)