【问题标题】:Problem with gRPC setup. Getting an intermittent RPC unavailable errorgRPC 设置问题。收到间歇性 RPC 不可用错误
【发布时间】:2019-03-30 07:13:49
【问题描述】:

我有一个 grpc 服务器和客户端,大部分时间都按预期工作,但偶尔会收到“传输正在关闭”错误:

rpc error: code = Unavailable desc = transport is closing

我想知道是不是我的设置有问题。客户端很基础

connection, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
pb.NewAppClient(connection)
defer connection.Close()

并且调用是在超时的情况下进行的,例如

ctx, cancel := context.WithTimeout(ctx, 300*time.Millisecond)
defer cancel()

client.MyGRPCMethod(ctx, params)

我正在做的另一件事是检查连接以查看它是打开、空闲还是正在连接,如果是,则重用连接。否则重拨。

服务器没有发生任何特殊配置

grpc.NewServer()

在设置 grpc 客户端/服务器时,我可能会犯什么常见错误吗?

【问题讨论】:

    标签: go rpc grpc


    【解决方案1】:

    我遇到了同样的问题 earlier this year 。大约 15 分钟后,我让服务器关闭了连接。

    我的有效解决方案是在我的main 函数上使用grpc.Dial 创建一次connection,然后在每个请求上创建pb.NewAppClient(connection)。由于 connection 已经创建,因此延迟不是问题。请求完成后,我关闭了客户端。

    【讨论】:

    • 这很有帮助,但不是一个很好的解决方案 - 重点应该是能够分享 ClientConn。无法找到一个可接受的理由来解释为什么会发生这种情况:(
    • 我同意这不是最好的解决方案,但由于连接超时,它会回避 transport is closing 错误。在遇到同样的问题后,我做了一些真实的测试,平均每次调用多出 1 毫秒。如果您的应用程序是 Web 应用程序,则它并不明显,特别是与其他慢 10 倍的语言(如 php、python、est)相比。
    • 刚刚发布了一个可能是更好解决方案的答案。让我知道你的想法
    【解决方案2】:

    我正在做的另一件事是检查连接以查看它是打开、空闲还是正在连接,如果是,则重用连接。否则,重拨。

    grpc 将为您管理您的连接,并在需要时重新连接,因此除非您有非常特殊的需要,否则您永远不需要在创建它后对其进行监控。

    “运输正在关闭”有许多不同的发生原因;请查看我们的常见问题解答中的相关问题,如果您仍有疑问,请告诉我们:https://github.com/grpc/grpc-go#the-rpc-failed-with-error-code--unavailable-desc--transport-is-closing

    【讨论】:

      【解决方案3】:

      经过大量搜索,我终于找到了一个可以接受且合乎逻辑的解决方案。

      根本原因是:底层 TCP 连接突然关闭,但 gRPC 客户端和服务器都没有“通知”此事件。

      挑战来自多个层面:

      • 内核对 TCP 套接字的管理
      • 任何中间负载平衡器/反向代理(由云提供商或其他方式提供)以及它们如何管理 TCP 套接字
      • 您的应用层本身及其网络要求 - 是否可以为未来的请求重用相同的连接

      结果证明我的解决方案相当简单:

      server = grpc.NewServer(
          grpc.KeepaliveParams(keepalive.ServerParameters{
              MaxConnectionIdle: 5 * time.Minute,           // <--- This fixes it!
          }),
      )
      

      这可确保 gRPC 服务器在内核或中间服务器突然终止之前优雅地关闭底层 TCP 套接字(AWS 和 Google Cloud 负载均衡器的超时时间均大于 5 分钟)。

      您会在这里发现的额外好处是,您使用多个连接的任何地方,忘记关闭连接的客户端引入的任何泄漏也不会影响您的服务器。

      我的 0.02 美元:不要盲目相信任何组织(甚至是 Google)设计和维护 API 的能力。这是一个典型的 defaults-gone-wrong 案例。

      【讨论】:

      • 我在我的本地主机上做了 20 分钟的测试,它保持了连接。今天下午我将继续尝试在 kubernetes 和 docker 中查看连接是否保持。如果可行,我同意谷歌需要更新文档。
      猜你喜欢
      • 2016-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 2016-05-20
      • 1970-01-01
      • 2023-03-07
      相关资源
      最近更新 更多