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)