如何取消GRPC流式调用?

Abh*_*kar 8 grpc grpc-java

通常,客户端可以通过以下方式取消 gRPC 调用:

(requestObserver as ClientCallStreamObserver<Request>)
    .cancel("Cancelled", null)
Run Code Online (Sandbox Code Playgroud)

但是,它在Javadoc中显示:

CancellableContext withCancellation = Context.current().withCancellation();
// do stuff
withCancellation.cancel(t);
Run Code Online (Sandbox Code Playgroud)

哪一种是取消客户端调用并让服务器知道的“正确”方法?

编辑:

让事情变得更加混乱的是,还有ManagedChannel.shutdown*.

Eri*_*son 1

两者都是可接受且适当的。

clientCallStreamObserver.cancel()通常更容易,因为它的样板代码更少。一般来说应该是首选。然而,它不是线程安全的;就像在 StreamObserver 上正常发送一样。它还需要直接了解 RPC;您无法让更高级别的代码协调取消,因为它甚至可能不知道 RPC。

使用Context取消来实现线程安全取消和较少 RPC 感知的取消。上下文取消可用于类似于线程中断或 Future 取消的情况。并不是说CancellableContexts 应该被视为资源并且最终必须被取消以避免内存泄漏。(context.cancel(null)当上下文达到其“正常”生命周期时可以使用。)

  • grpc-kotlin 根本不使用 StreamObserver API;它直接使用较低级别的 ClientCall 作为其存根(这是合适的)。简单地说,“您没有使用 grpc-java 存根”。`channel.shutdown()` 不会取消 RPC。`shutdownNow()` 可以,但是对于取消单个 RPC 来说它会非常糟糕。 (2认同)