首页 > 解决方案 > Java gRPC:从客户端到服务器的异常

问题描述

是否可以从客户端向服务器抛出异常?我们有一个从服务器到客户端的开放流:

rpc addStream(Request) returns (stream StreamMessage) {}     

当我尝试这样的事情时:

throw Status.INTERNAL.withDescription(e.getMessage()).withCause(e.getCause()).asRuntimeException();

我在客户端的 StreamObserver.onError 中得到了异常,但在服务器端没有异常。

标签: grpcgrpc-java

解决方案


服务器可以使用存根 API 公开为StatusRuntimeException. 然而,客户端只能“取消” RPC。服务器将不知道取消的来源;这可能是因为客户端取消或 TCP 连接中断。

在客户端流式传输或双向流式调用中,客户端可以通过调用取消observer.onError()(无需调用onCompleted())。但是,如果客户端调用onCompleted()或 RPC 有一个一元请求,那么您需要使用ClientCallStreamObserveror Context

stub.someRpc(request, new ClientResponseObserver<Request, Response>() {
  private ClientCallStreamObserver<Request> requestStream;

  @Override public void beforeStart(ClientCallStreamObserver<Request> requestStream) {
    this.requestStream = requestStream;
  }
  ...
});

// And then where you want to cancel

// RequestStream is non-thread-safe. For unary requests, wait until
// stub.someRpc() returns, since it uses the stream internally.
// The string is not sent to the server. It is just "echoed"
// back to the client's `onError()` to make clear that the
// cancellation was locally caused.
requestStream.cancel("some message for yourself", null);


// For thread-safe cancellation (e.g., for client-streaming)
CancellableContext ctx = Context.current().withCancellation();
StreamObserver requestObserver = ctx.call(() ->
  stub.someRpc(new StreamObserver<Response>() {
    @Override public void onCompleted() {
      // The ctx must be closed when done, to avoid leaks
      ctx.cancel(null);
    }

    @Override public void onError() {
      ctx.cancel(null);
    }
  }));

// The place you want to cancel
ctx.cancel(ex);

推荐阅读