我有一个 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 客户端/服务器时是否存在任何常见错误?
经过多次搜索,我终于找到了一个可以接受且合乎逻辑的解决方案来解决这个问题。
根本原因是这样的:底层TCP连接突然关闭,但 gRPC 客户端和服务器都不会“通知”此事件。
挑战来自多个层面:
- 内核对TCP套接字的管理
- 任何中间负载均衡器/反向代理(由云提供商或其他方式)以及它们如何管理 TCP 套接字
- 您的应用程序层本身及其网络要求 - 是否可以为将来的请求重用相同的连接
我的解决方案结果相当简单:
server = grpc.NewServer(
grpc.KeepaliveParams(keepalive.ServerParameters{
MaxConnectionIdle: 5 * time.Minute, // <--- This fixes it!
}),
)
这可以确保 gRPC 服务器在内核或中间服务器突然终止之前正常关闭底层 TCP 套接字(AWS 和 Google Cloud Load Balancer 的超时时间都超过 5 分钟)。
您在这里还会发现的额外好处是,在任何使用多个连接的地方,忘记关闭连接的客户端引入的任何泄漏也不会影响您的服务器。
我的 0.02 美元:不要盲目相信任何组织(甚至谷歌)设计和维护API的能力。这是默认错误的典型案例。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)