作者:大东o世界 | 来源:互联网 | 2022-12-01 13:38
我有一个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客户端/服务器是否存在任何常见错误?
1> Angad..:
经过大量的搜索,我终于找到了可以解决该问题的合理方法。
根本原因是这样的:底层的TCP连接突然关闭,但是gRPC客户端和服务器均未“通知”该事件。
挑战来自多个层面:
内核对TCP套接字的管理
任何中间负载平衡器/反向代理(通过云提供商或其他方式)以及它们如何管理TCP套接字
您的应用程序层本身及其对网络的要求-是否可以将相同的连接重新用于将来的请求?
我的解决方案非常简单:
server = grpc.NewServer(
grpc.KeepaliveParams(keepalive.ServerParameters{
MaxConnectionIdle: 5 * time.Minute, // <--- This fixes it!
}),
)
这样可以确保gRPC服务器在内核或中间服务器突然中断之前(AWS和Google Cloud Load Balancers的超时都超过5分钟),先自行正常关闭基础TCP套接字。
您还将在这里找到的额外好处是,在使用多个连接的任何地方,客户端导致的忘记关闭连接的任何泄漏也不会影响您的服务器。
我的0.02美元:不要盲目相信任何组织(甚至是Google)设计和维护API的能力。这是defaults-gone-wrong的经典案例。