使用Protobuf3和grpc实现RPC调用
本文展示了通过Protobuf3定义服务接口并通过grpc实现简单的RPC调用
源代码:
https://github.com/JasonkayZK/Go_Learn/tree/protobuf_grpc_demo
使用Protobuf3和grpc实现RPC调用 使用Protobuf是还需要安装protoc和protoc-gen-go以支持通过.proto生成对应的接口;
下面以在windows下为例介绍protoc和protoc-gen-go的安装(protoc底层调用的是protoc-gen-go )
安装protoc和protoc-gen-go protoc Github的Release下载:
https://github.com/protocolbuffers/protobuf/releases
下载对应平台的压缩包(win/Linux);
解压之后将bin目录下的protoc复制到系统环境变量的路径下:
win: C:\Windows\System32
Linux: /bin
等等;
然后测试:
1 2 protoc --version libprotoc 3.12.0
protoc-gen-go Github的Release下载:
https://github.com/golang/protobuf/releases
下载压缩包并解压;
解压后在protoc-gen-go目录下编译:
然后将生成的二进制文件protoc-gen-go复制到系统环境变量的路径下
全部安装完成!
目录结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 tree /F . │ go.mod │ go.sum │ ├─hello_client │ main.go │ ├─hello_server │ main.go │ └─proto hello.pb.go hello.proto
编写proto 本例子使用proto3语法;
hello.proto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 syntax = "proto3" ; package proto;message HelloRequest { string name = 1 ; } message HelloResponse { string message = 1 ; } service Hello { rpc SayHello (HelloRequest) returns (HelloResponse) ; }
编写完成之后使用protoc生成.pb.gp文件:
1 protoc -I . --go_out=plugins=grpc:. ./hello.proto
即可生成hello.pb.go文件
初始化gomod项目 使用go mod init protobuf_grpc_demo初始化项目;
生成go.mod文件;
然后使用go mod tidy初始化;
服务端代码 hello_server/main.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 package mainimport ( "context" "fmt" "google.golang.org/grpc" "net" pb "protobuf_grpc_demo/proto" ) const ( Address = "127.0.0.1:50052" ) type helloService struct {}func (s helloService) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error ) { resp := new (pb.HelloResponse) fmt.Printf("Get remote call from client, the context is: %s\n\n" , ctx) resp.Message = "hello " + in.Name + "." fmt.Printf("Response msg: " + resp.Message) return resp, nil } var HelloService = helloService{}func main () { listen, err := net.Listen("tcp" , Address) if err != nil { fmt.Printf("Failed to listen: %v" , err) } s := grpc.NewServer() pb.RegisterHelloServer(s, HelloService) println ("Listen on: " + Address) _ = s.Serve(listen) }
客户端代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package mainimport ( "context" "fmt" "google.golang.org/grpc" pb "protobuf_grpc_demo/proto" ) const ( Address = "127.0.0.1:50052" ) func main () { conn, err := grpc.Dial(Address, grpc.WithInsecure()) if err != nil { fmt.Printf("Failed to dial to: " + Address) } if conn == nil { panic ("Failed to get connection from the server" ) } defer conn.Close() c := pb.NewHelloClient(conn) reqBody := new (pb.HelloRequest) reqBody.Name = "gRPC" r, err := c.SayHello(context.Background(), reqBody) if err != nil { fmt.Printf("Fail to call method, err: %v" , err) } fmt.Println(r.Message) }
运行测试 1 2 3 4 5 6 7 8 9 10 11 12 13 D:\workspace\go_learn>go run hello_server/main.go Listen on: 127.0.0.1:50052 D:\workspace\go_learn>go run hello_client/main.go hello gRPC. Get remote call from client, the context is: context.Background.WithCancel.WithValue(type peer.peerKey, val <not Stri nger>).WithValue(type metadata.mdIncomingKey, val <not Stringer>).WithValue(type grpc.streamKey, val <not Stringer>) Response msg: hello gRPC.
附录 源代码:
https://github.com/JasonkayZK/Go_Learn/tree/protobuf_grpc_demo
如果觉得文章写的不错, 可以关注微信公众号: Coder张小凯
内容和博客同步更新~