【问题标题】:Go gRPC Client Connection Scope and PoolingGo gRPC 客户端连接范围和池化
【发布时间】:2018-07-04 15:52:21
【问题描述】:

考虑来自 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)
}

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

例如

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

【问题讨论】:

  • 如果您打算很快发出更多请求,您应该保持连接打开并重用它。否则,或者如果您的资源非常紧张,您应该立即关闭它。不过,用您当前的示例确实无法判断。
  • 当然,这个例子是从 grpc repo 中摘取的,目的是让我清楚我所说的连接的意思。必须有一些关于如何使用连接的文档......例如并发使用是否安全?
  • 它们可以安全地同时使用。不过,您有一点,可以使用一些文档。看来you're not the only one是这么想的。

标签: go grpc


【解决方案1】:

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

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

  1. 客户端上的 gRPC 连接池与服务器端 TCP(第 4 层)负载平衡器相结合。这将最初创建一个客户端连接池,并将此连接池重新用于后续 gRPC 请求。在我看来,这是更容易实现的途径。请参阅Pooling gRPC Connections,了解使用grpc-go-pool 库的grpc 客户端上的grpc 连接池示例。
  2. HTTP/2(第 7 层)负载平衡器,支持 gRPC 以实现负载平衡请求。请参阅gRPC Load Balancing,它概述了不同的 grpc 负载平衡选项。 nginx 最近added support for gRPC load balancing.

【讨论】:

    猜你喜欢
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 2021-09-27
    • 2017-08-04
    • 1970-01-01
    • 2012-06-13
    相关资源
    最近更新 更多