gRPC设置问题。出现间歇性RPC不可用错误

时间:2018-10-25 15:39:34

标签: go rpc grpc

我有一个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客户端/服务器时是否有常见错误?

3 个答案:

答案 0 :(得分:3)

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

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

挑战来自多个层面:

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

我的解决方案非常简单:

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

这可确保gRPC服务器在内核或中介服务器突然终止之前(AWS和Google Cloud Load Balancer的超时都超过5分钟),先自行正常关闭基础TCP套接字。

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

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

  

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

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

“运输正在关闭”发生的原因有很多。请在我们的常见问题解答中查看相关问题,并让我们知道您是否还有问题:https://github.com/grpc/grpc-go#the-rpc-failed-with-error-code--unavailable-desc--transport-is-closing