🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 安装 1、安装gRPC runtime ``` go get google.golang.org/grpc ``` 为了自动生成Golang的gRPC代码,需要安装protocal buffers compiler以及对应的GoLang插件 2、protocal buffer安装 从https://github.com/google/protobuf/releases下载安装包,例如:protobuf-cpp-3.0.0-beta-3.zip,解压后 ``` ./configure make && make install ``` 再添加环境变量: ``` export LD_LIBRARY_PATH=/usr/local/lib ``` 之后protoc命令即可运行 ## 生成pb.go文件 定义protobuf helloworld.proto ``` syntax = "proto3"; package helloworld; // The greeter service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) { } } // The request message containing the user's name. message HelloRequest { string name = 1; int32 age = 2; } // The response message containing the greetings message HelloReply { string message = 1; } ``` 执行 protoc ``` protoc --go_out= plugins=grpc: . helloworld.proto ``` ## 编写服务端 ``` package helloworld // server.go import ("golang.org/x/net/context" "net" "google.golang.org/grpc" ) const (port =":50051") type server struct {} func (s *server) SayHello(ctx context.Context, in *HelloRequest) (*HelloReply, error) { return &HelloReply{"go"}, nil } func Run(){ lis, err := net.Listen("tcp", port) if err!=nil{ return } s:= grpc.NewServer() RegisterGreeterServer(s, &server{}) s.Serve(lis) } ``` ## 编写客户端 ``` package helloworld import ( "google.golang.org/grpc" "context" "fmt" ) // client.go const ( address = "localhost:50051" defaultName = "world" defaultAge = int32(25) ) func RunClient() { conn, err := grpc.Dial(address, grpc.WithInsecure()) if err != nil { return } defer conn.Close() c := NewGreeterClient(conn) name := defaultName age := defaultAge r, err := c.SayHello(context.Background(), &HelloRequest{Name:name, Age:age}) fmt.Println(r.Message) } ``` ## protobuf依赖 -I , -I=IMPORT_PATH  can be used as a short form of --proto_path 简单来说,就是如果多个proto文件之间有互相依赖,生成某个proto文件时,需要import其他几个proto文件,这时候就要用-I来指定搜索目录。 如果没有指定 –I 参数,则在当前目录进行搜索。 ``` protoc --go_out=./go/ -I/usr/local/include ./proto/helloworld.proto ``` ## 项目中实际使用 新建grpc server ``` kpOpt := grpc.KeepaliveParams( keepalive.ServerParameters{ // 长连接ping时间 Time: 60 * time.Second, // 超时时间 Timeout: 3 * time.Second, }, ) s := grpc.NewServer(kpOpt) ``` 新建一个用来连接的server实例, 初始化数据库连接和配置 ``` type ( HistoryServer struct { cfg *conf.Config model *HistoryModel } ) func NewHistoryServer(cfg *conf.Config) (server *HistoryServer, err error) { var m *HistoryModel var db *DBModel if db, err = NewDBModel(cfg.Database.DbDriver, cfg.Database.DbSource); err == nil { if m, err = NewHistoryModel(cfg.Default.MongoUri, db); err == nil { server = &HistoryServer{cfg: cfg, model: m} } } return } ``` ``` historyServ, err := NewHistoryServer(cfg) if err != nil { logger.Error("failed to init server:", zap.Error(err)) return } history_api.RegisterHistoryServiceServer(s, historyServ) l, err := net.Listen("tcp", ":"+cfg.Default.RpcPort) if err != nil { logger.Error("rpc: ", zap.String("listen", cfg.Default.RpcPort), zap.Error(err)) return } go s.Serve(l) ``` ## 开启gzip压缩 开启grpc服务时 导入gzip包 ``` _ "google.golang.org/grpc/encoding/gzip" ``` 会在这个包init时带上压缩解压缩机制 grpc-gateway也要带上参数: ``` opts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithMaxMsgSize(100 * 1024 * 1024), grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip") ``` ## 客户端超时设置 ``` resp = self.stub.GetHistoryBars(req, metadata=[ (str('authorization'), context.token), (str('grpc-internal-encoding-request'), str('gzip')), (str('grpc-timeout'), str('10S')) ]) ```