java - gRPC 客户端重新连接逻辑导致服务器端打开重复的流

标签 java grpc grpc-java

我有一个使用两个双向流的 gRPC 客户端。由于目前未知的原因,当我们每小时发送一次 keepAlive ping 时,两个流上都会调用带有 statusRuntimeException 的 onError。

为了处理重新连接,我在 java 伪代码中实现了以下重试机制。我会在评论中根据需要澄清任何内容。

该机制如下所示:

onError() {
    retrySyncStream();
}


void retrySyncStream() {
    // capture the current StreamObserver
    previousStream = this.StreamObserver;

    // open a new stream
    streamObserver = bidiStub.startStream(responseObserver);

    waitForChannelReady(); // <-- simplified version, we use the gRPC notification listener 

    previousStream.onCompleted(); // <-- called on notify of channel READY

}

尽管我们尝试关闭旧流,但服务器端我们看到 2 个 HA 节点上打开了 2 个连接。我无法控制服务器端的任何内容,我只需要处理客户端上的重新连接逻辑。

首先,在收到 StatusRuntimeException 后抛弃旧的 StreamObserver 是常见做法吗?我这样做的原因是因为我们有一个模拟服务器 Spring Boot 应用程序,我们用它来测试我们的客户端。当我强制关闭 (Ctl-c) Spring Boot 服务器应用程序并再次启动它时,客户端无法使用原始 StreamObserver,它必须通过调用 gRPC bidi 流 API 调用来创建一个新的 StreamObserver。

根据我在网上读到的内容,人们说不要放弃托管 channel ,但是流观察者怎么样,并确保多个流不会被错误地打开? 谢谢。

最佳答案

当 StreamObserver 出现错误时,RPC 就终止了。抛弃它是合适的。

当您重新创建流时,请考虑如果服务器出现问题会发生什么情况。一般来说,你会在某个地方设置指数退避。对于双向流情况,如果客户端收到服务器的响应,gRPC 中的几种情况往往会重置退避。

由于两个流同时死亡,听起来 TCP 连接已死亡。不幸的是,在 TCP 中,您必须在连接上发送数据才能得知它已失效。当客户端得知连接已断开时,它会得知这是因为它无法使用该连接向 HA 代理发送数据。这意味着 HA 必须单独发现连接已断开。服务器端 keepalive 可以对此有所帮助,尽管 HA 处的 TCP keepalive 也可能是有保证的。

关于java - gRPC 客户端重新连接逻辑导致服务器端打开重复的流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71851301/

相关文章:

java - 如何在 Spring MVC 中解决 HTTP 404 状态?

python - 如何知道 GRPC 服务器是否可用

grpc - 为 Hyperledger fabric V1.0 编写 gRPC 客户端

java - Android clazz.getConstructors() 返回错误数量的构造函数,仅在实时应用程序中

Java 8 Lambda Chaining - 类型安全执行

java - 如何为 java/jsf 代码创建自己的解析器?

protocol-buffers - 跨微服务共享原始文件或生成的文件

node.js - 你如何在 TypeScript 中实现 GRPC 服务器?

c++ - gRPC 错误返回意外的详细信息字段

grpc - 将元数据添加到 proto3 for Java 中的字段