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

har*_*rog 5 rpc go grpc

我有一个grpc服务器和客户端,大多数时候都能正常工作,但是偶尔会收到“传输正在关闭”错误:

rpc error: code = Unavailable desc = transport is closing
Run Code Online (Sandbox Code Playgroud)

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

connection, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
pb.NewAppClient(connection)
defer connection.Close()
Run Code Online (Sandbox Code Playgroud)

并以类似超时的方式拨打电话

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

client.MyGRPCMethod(ctx, params)
Run Code Online (Sandbox Code Playgroud)

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

服务器没有任何特殊配置

grpc.NewServer()
Run Code Online (Sandbox Code Playgroud)

设置我可能正在设置的grpc客户端/服务器是否存在任何常见错误?

Ang*_*gad 6

经过大量的搜索,我终于找到了可以解决该问题的合理方法。

根本原因是这样的:底层的TCP连接突然关闭,但是gRPC客户端和服务器均未“通知”该事件。

挑战来自多个层面:

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

我的解决方案非常简单:

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

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

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

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


Dou*_*ley 4

我正在做的另一件事是检查连接以查看它是否处于打开、空闲或连接状态,如果是,则重新使用该连接。否则,重拨。

grpc 将为您管理您的连接,并在需要时重新连接,因此您不需要在创建它后监视它,除非您有非常具体的需求。

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