go grpc 服务器不知道客户端不优雅死了
go grpc server doesn't known client ungraceful dead
我正在使用 go-grpc 创建双向流。当我拔下电缆时,服务器在很长一段时间内都不知道客户端已死。在这种情况下,我如何检测到客户端已消失???
您的 GRPC
服务器端处理程序将在下次尝试 Send
/Recv
消息 to/from 流时了解客户端上下文取消:错误将被退回:
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,进行测试?
我遇到了和你完全一样的问题。在我的例子中,当我使用 Ctrl-C 终止我的测试客户端时,服务器很快检测到它,但是当我使用 Ctrl-Z(或者如果我切断微控制器的电源)时,服务器将永远关闭挂连接。您需要使用某种心跳来检查连接,例如使用 gRPC 的 keepAlive 功能。由于在 Envoy 后面使用 gRPC 时出现问题,我不得不创建自己定期发送的心跳消息 (https://github.com/envoyproxy/envoy/issues/2086)
我正在使用 go-grpc 创建双向流。当我拔下电缆时,服务器在很长一段时间内都不知道客户端已死。在这种情况下,我如何检测到客户端已消失???
您的 GRPC
服务器端处理程序将在下次尝试 Send
/Recv
消息 to/from 流时了解客户端上下文取消:错误将被退回:
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,进行测试?
我遇到了和你完全一样的问题。在我的例子中,当我使用 Ctrl-C 终止我的测试客户端时,服务器很快检测到它,但是当我使用 Ctrl-Z(或者如果我切断微控制器的电源)时,服务器将永远关闭挂连接。您需要使用某种心跳来检查连接,例如使用 gRPC 的 keepAlive 功能。由于在 Envoy 后面使用 gRPC 时出现问题,我不得不创建自己定期发送的心跳消息 (https://github.com/envoyproxy/envoy/issues/2086)