【发布时间】:2017-12-21 09:53:00
【问题描述】:
我正在使用 go-grpc 创建双向流。当我拔下电缆时,服务器不知道客户端死了很长时间。在这种情况下如何检测客户端已消失???
【问题讨论】:
我正在使用 go-grpc 创建双向流。当我拔下电缆时,服务器不知道客户端死了很长时间。在这种情况下如何检测客户端已消失???
【问题讨论】:
我遇到了和你一样的问题。在我的情况下,当我使用 Ctrl-C 终止我的测试客户端时,服务器很快检测到它,但是当我使用 Ctrl-Z(或者如果我切断微控制器的电源)时,服务器将永远关闭悬挂连接。您需要使用某种心跳来检查连接,使用诸如 gRPC 的 keepAlive 功能之类的东西。由于在 Envoy 后面使用 gRPC 时出现问题,我不得不创建自己的心跳消息并定期发送 (https://github.com/envoyproxy/envoy/issues/2086)
【讨论】:
您的GRPC 服务器端处理程序将在下次尝试向/从流发送Send/Recv 消息时了解客户端上下文取消:将返回错误:
func (s *server) handler(stream your_service.Stream) error {
if err := stream.Recv(); err != nil {
// you will have context cancelation error here
}
}
在某些情况下,明确检查上下文取消可能很有用:
func (s *server) handler(stream your_service.Stream) error {
// some logic
select {
case <-stream.Context().Done():
return stream.Context().Err()
default:
}
}
顺便说一句,你真的拔掉电缆吗?因为操作系统可能会以不同的方式处理它。为什么不使用任何现代虚拟化工具(例如 Docker)进行测试?
【讨论】:
stream.Recv() 进行检测。我确实使用了第二种方式,观察stream.Context().Done(),但是花了很长时间才注意到客户端已经消失了。我将实现我自己的心跳来让它工作。