找回密码
 立即注册
首页 业界区 安全 [tldr] go使用gRPC

[tldr] go使用gRPC

忿媚饱 7 天前
gRPC是谷歌推出的一个rpc服务框架, 数据编码采用protobuf实现.
安装环境
  1. go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
  2. go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
复制代码
缺少可能导致出现可执行程序没有找到的报错, 可以参考stackoverflow的帖子
文件
  1. syntax = "proto3";
  2. option go_package = "./myproto";
  3. package myproto;
  4. message Hello {
  5.   string name = 1;
  6. }
  7. service HelloService {
  8.   rpc SayHello (Hello) returns (Hello);
  9. }
复制代码
分别需要message和service2个部分的内容
编译
  1. ./bin/bin/protoc --go_out=. ./myproto/hello.proto
  2. ./bin/bin/protoc --go-grpc_out=. ./myproto/hello.proto
复制代码
使用上述指令编译为符合grpc使用的服务, 一个是message的定义的GO实现, 一个是service的定义的GO实现
根据grpc官方文档应该采用类似以下的指令实现, 效果是一样的
  1. protoc --go_out=. --go_opt=paths=source_relative \
  2.     --go-grpc_out=. --go-grpc_opt=paths=source_relative \
  3.     ./myproto/hello.proto
复制代码

  • 本质是编译message和编译rpc的service
使用

以下代码为生成出来的go的grpc的服务的代码
  1. // HelloServiceClient is the client API for HelloService service.
  2. //
  3. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
  4. type HelloServiceClient interface {
  5.         SayHello(ctx context.Context, in *Hello, opts ...grpc.CallOption) (*Hello, error)
  6. }
  7. type helloServiceClient struct {
  8.         cc grpc.ClientConnInterface
  9. }
  10. func NewHelloServiceClient(cc grpc.ClientConnInterface) HelloServiceClient {
  11.         return &helloServiceClient{cc}
  12. }
  13. func (c *helloServiceClient) SayHello(ctx context.Context, in *Hello, opts ...grpc.CallOption) (*Hello, error) {
  14.         cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
  15.         out := new(Hello)
  16.         err := c.cc.Invoke(ctx, HelloService_SayHello_FullMethodName, in, out, cOpts...)
  17.         if err != nil {
  18.                 return nil, err
  19.         }
  20.         return out, nil
  21. }
复制代码
这些是自动生成的文件内容
Server
  1. // HelloServiceServer is the server API for HelloService service.
  2. // All implementations must embed UnimplementedHelloServiceServer
  3. // for forward compatibility.
  4. type HelloServiceServer interface {
  5.         SayHello(context.Context, *Hello) (*Hello, error)
  6.         mustEmbedUnimplementedHelloServiceServer()
  7. }
复制代码
以上代码是编译器自动生成的GO代码
Client
  1. // HelloServiceClient is the client API for HelloService service.
  2. //
  3. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
  4. type HelloServiceClient interface {
  5.         SayHello(ctx context.Context, in *Hello, opts ...grpc.CallOption) (*Hello, error)
  6. }
复制代码
以上为自动编译生成的代码
启动服务

在自己编写的代码中使用上述生成的代码
可以参考go-grpc官方仓库样例代码
server
  1. package main
  2. import (
  3.         "context"
  4.         "fmt"
  5.         "log"
  6.         "myrpc/myproto"
  7.         "net"
  8.         "google.golang.org/grpc"
  9. )
  10. const (
  11.         PORT = 1234
  12. )
  13. type Server struct {
  14.         myproto.UnimplementedHelloServiceServer
  15. }
  16. func (s *Server) SayHello(ctx context.Context, in *myproto.Req) (*myproto.Res, error) {
  17.         log.Printf("Received: %v", in.Name)
  18.         return &myproto.Res{Message: "Hello " + in.Name}, nil
  19. }
  20. func main() {
  21.         list, err := net.Listen("tcp", fmt.Sprintf(":%d", PORT))
  22.         if err != nil {
  23.                 log.Printf("failed to listen: %v", err)
  24.         }
  25.         log.Printf("server listening at :%d", PORT)
  26.         grpcServer := grpc.NewServer()
  27.         myproto.RegisterHelloServiceServer(grpcServer, &Server{})
  28.         grpcServer.Serve(list)
  29. }
复制代码
整体实现和常见的rpc类似
client
  1. package main
  2. import (
  3.         "context"
  4.         "fmt"
  5.         "myrpc/myproto"
  6.         "time"
  7.         "google.golang.org/grpc"
  8.         "google.golang.org/grpc/credentials/insecure"
  9. )
  10. const (
  11.         PORT = 1234
  12. )
  13. func main() {
  14.         conn, err := grpc.NewClient(fmt.Sprintf(":%d", PORT), grpc.WithTransportCredentials(insecure.NewCredentials()))
  15.         if err != nil {
  16.                 panic(err)
  17.         }
  18.         defer conn.Close()
  19.         c := myproto.NewHelloServiceClient(conn)
  20.         ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  21.         defer cancel()
  22.         res, err := c.SayHello(ctx, &myproto.Req{Name: "xuhe"})
  23.         if err != nil {
  24.                 panic(err)
  25.         }
  26.         fmt.Println(res.GetMessage())
  27. }
复制代码
FQ

常见报错
  1. panic: grpc: no transport security set (use grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly or set credentials)
  2. goroutine 1 [running]:
  3. main.main()
  4.         /home/xuhe/tmp/go/rpc/cmd/client/main.go:18 +0x1d4
  5. exit status 2
复制代码
需要手动设置为conn, err := grpc.NewClient(fmt.Sprintf(":%d", PORT), grpc.WithTransportCredentials(insecure.NewCredentials()))不安全的实现方式
参考

grpc使用GO官方文档

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册