【gRPC】快速开始 | Go

Prerequisites(先决条件)

  • Go
    Go的三个最新主要版本之一
  • Protocol buffer 编译器,protoc,version3
    https://www.jianshu.com/p/5324b412f1de
  • protocol 编译器的 Go 插件:
    https://www.jianshu.com/p/5324b412f1de

获取示例代码

  1. 下载实例代码
    $ git clone -b v1.46.0 --depth 1 https://github.com/grpc/grpc-go
    
  2. 切换代码目录
    $ cd grpc-go/examples/helloworld
    

运行示例

在 examples/helloworld 目录下:

  1. 编译和执行服务端代码
    $ go run greeter_server/main.go
    
  2. 在另外一个终端中,编译和执行客户端代码,会看到客户端输出:
    $ go run greeter_client/main.go
    Greeting: Hello world
    

更新 gRPC 服务

在本节中,将使用额外的 server 方法更新应用程序。gRPC服务是使用 protocol buffers 定义的。
现在,只需要知道服务器和客户端存根都有一个 SayHello()RPC方法,该方法从客户端获取一个 HelloRequest 参数,并从服务器返回一个 HelloReply,该方法的定义如下:

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

打开 helloworld/helloworld.proto,添加一个新的方法 SayHelloAgain()

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

重新生成 gRPC 代码

在可以使用新的服务方法之前,需要重新编译更新后的 .proto 文件。
在 examples/helloworld 目录下,运行下面的命令:

$ protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
helloworld/helloworld.proto

paths:用于指定生成文件的路径的结构,有两个值:
1. paths=import 相对于导入路径, 默认值
2. paths=source_relative 相对于输入文件,即proto文件的路径

重新生成的 helloworld/helloworld.pb.go 和 helloworld/helloworld_grpc.pb.go 文件中包含:

  • xxx.pb.go
    它包含用于填充、序列化和检索 请求和响应消息类型 的所有protocol buffer 代码。
  • xxx_grpc.pb.go
    客户端使用的 服务中定义的方法调用的接口类型(或存根)。
    服务器要实现的接口类型。

更新并运行应用程序

虽然已经生成了客户端、服务端代码,但是任然需要示例程序中 实现和调用 新的方法。

  1. 更新 服务端
    打开 greeter_server/main.go 添加下面的函数:
    func (s *server) SayHelloAgain (ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
      retrn &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
    }
    
  2. 更新客户端
    打开 greeter_client/main.go 在 main() 函数体的最下方添加下面代码:
    r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
      log.Fatalf("could not greet : %v", err)
    }
    log.Printf("Greetine : %s", r.GetMessage())
    
  3. 运行
    # 运行 server
    go run greeter_server/main.go
    
    # 运行 client
    go run greeter_client/main.go Alice
    
    # client 输出
    2021/05/15 23:55:08 Greeting: Hello Alice
    2021/05/15 23:55:08 Greeting: Hello again Alice
    

总结

  • gRPC基本使用流程
  1. .proto 文件中定义 service、message

  2. 通过 protocol buffer 编译器生成代码

  3. 创建服务端
    3.1 实现 servic 中定义的接口
    gRPC 允许你定义四种类型的服务方法

    3.2 启动一个gRPC 服务,监听客户端请求
    一旦你实现了所有的方法,我们需要启动一个 gRPC 服务,目的是客户端能够使用我们的服务。
    如何构建并启动一个服务:
    3.2.1 指定用于 监听客户端请求的端口
    lis, err := net.Listen(...)

    3.2.2 创建一个 gRPC 服务实例
    grpcServer := grpc.NewServer(...)

    3.2.3 在 gRPC服务器上注册我们的服务实现
    pb.RegisterRouterGuideServer(...)

    3.2.4 在服务器上使用 端口详细信息 调用Serve() 方法,以执行阻塞等待,直到进程被终止 或 调用 Stop()
    grpcServer.Serve(...)

    lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))
    if err != nil {
      log.Fatalf("failed to listen: %v", err)
    }
    
    var opts []grpc.ServerOption
    ...
    grpcServer := grpc.NewServer(opts...)
    pb.RegisterRouteGuideServer(grpcServer, newServer())
    grpcServer.Serve(lis)
    
  4. 创建客户端

  5. 创建一个stub
    要调用服务方法,我们首先需要创建一个gRPC通道来与服务器通信。我们通过将服务器地址和端口号传递给 grpc.Dial() 来创建它,如下所示:

    var opts []grpc.DialOption
    ...
    conn, err := grpc.Dial(*serverAddr, opts...)
    if err != nil {
    ...
    }
    defer conn.Close()
    

    可以使用 DialOptions 在 grpc.Dial 中设置身份验证凭据(例如,TLS、GCE凭据或JWT凭据),当服务需要这些凭据时可以使用它们。

    一旦 gRPC通道 设置好,我们就需要一个客户端存根来执行RPC。我们使用从 .proto文件 生成的 pb包 提供的 NewRouteGuideClient方法 获得它。

    client := pb.NewRouteGuideClient(conn)
    
  6. 调用服务方法
    gRPC允许定义四种类型的服务方法

  7. 执行客户端、服务端应用程序

你可能感兴趣的:(【gRPC】快速开始 | Go)