我有一个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客户端/服务器时是否有常见错误?
答案 0 :(得分:3)
经过大量的搜索,我终于找到了一个可以接受且合乎逻辑的解决方案。
根本原因是: 基础TCP连接突然关闭,但是gRPC客户端和服务器都没有“通知”该事件。
挑战来自多个层面:
我的解决方案非常简单:
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