Go gRPC 客户端连接范围和池化

Myl*_*ell 8 go grpc

考虑 Go gRPC 代码库中的示例:

func main() {
    // Set up a connection to the server.
    conn, err := grpc.Dial(address, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)

    // Contact the server and print out its response.
    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.Message)
}
Run Code Online (Sandbox Code Playgroud)

当从另一个服务使用 gRPC 服务时,连接 ( conn)的范围应该是什么?我认为它应该与正在处理的请求的范围是消费者服务有密切关系,但我还没有找到任何关于此的文档。我应该在这里使用连接池吗?

例如

  1. gRPC 消费者服务接收请求
  2. 建立与 gRPC 服务的连接(直接或通过池)
  3. 向 gRPC 服务发出n 个请求
  4. 关闭 gRPC 连接(或释放回池)

Agr*_*rim 11

根据经验,gRPC 客户端连接应该在客户端应用程序的生命周期内重复使用,因为它们可以安全地并发使用。此外,gRPC 的关键特性之一是远程过程调用的快速响应,如果您必须在收到每个请求时重新连接,则无法实现这一点。

尽管如此,强烈建议使用某种 gRPC 负载平衡以及这些持久连接。否则,大量负载可能最终会出现在一些长期存在的 grpc 客户端-服务器连接上。负载平衡选项包括:

  1. 客户端的 gRPC 连接池与服务器端 TCP(第 4 层)负载均衡器相结合。这将首先创建一个客户端连接池,并在随后的 gRPC 请求中重新使用这个连接池。在我看来,这是更容易实施的途径。有关使用grpc-go-pool库的grpc 客户端上的 grpc 连接池示例,请参阅池化 gRPC 连接
  2. HTTP/2(第 7 层)负载均衡器,具有对负载均衡请求的 gRPC 支持。请参阅gRPC 负载平衡,其中概述了不同的 grpc 负载平衡选项。nginx 最近添加了对 gRPC 负载平衡的支持