Spring Boot gRPC:发生业务错误时如何返回错误码?

我正在使用LogNet grpc-spring-boot-starter实现 gRPC API 。

例如,INVALID_ARGUMENT当传递了不正确的参数时,我想返回一个错误代码。

如果我抛出自定义异常,它会以io.grpc.StatusRuntimeException: UNKNOWN.

问:是否可以定义一些异常处理机制,使特定类型的异常始终导致正确的 gRPC 状态?

不幸的是,项目中没有那么多文档。


杨__羊羊
浏览 271回答 4
4回答

MM们

gRPC 不鼓励您抛出异常以将该错误传达给用户。这是因为意外泄露您可能没有考虑发送给客户的信息是微不足道的。相反,我们鼓励您将StatusExceptionor传递StatusRuntimeException给streamObserver.onError(Throwable). 如果您使用异常在您自己的代码中传达此信息,您可以在您的代码中放置一个 try-catch 并将异常传递给onError(). 例如,这对于 可能是公平的StatusException,因为它是一个已检查的异常。有TransmitStatusRuntimeExceptionInterceptor将在回调期间捕获异常,如果它是StatusRuntimeException,则关闭异常状态的调用。这与您的要求非常匹配,但默认情况下并未故意启用。

桃花长相依

我刚刚发表了一篇关于gRPC Java 中的异常处理和错误传播主题的文章。您可以使用拦截器处理异常,例如:public class ExceptionHandler implements ServerInterceptor {&nbsp; &nbsp; @Override&nbsp; &nbsp; public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ServerCallHandler<ReqT, RespT> serverCallHandler) {&nbsp; &nbsp; &nbsp; &nbsp; ServerCall.Listener<ReqT> listener = serverCallHandler.startCall(serverCall, metadata);&nbsp; &nbsp; &nbsp; &nbsp; return new ExceptionHandlingServerCallListener<>(listener, serverCall, metadata);&nbsp; &nbsp; }&nbsp; &nbsp; private class ExceptionHandlingServerCallListener<ReqT, RespT>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; extends ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT> {&nbsp; &nbsp; &nbsp; &nbsp; private ServerCall<ReqT, RespT> serverCall;&nbsp; &nbsp; &nbsp; &nbsp; private Metadata metadata;&nbsp; &nbsp; &nbsp; &nbsp; ExceptionHandlingServerCallListener(ServerCall.Listener<ReqT> listener, ServerCall<ReqT, RespT> serverCall,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Metadata metadata) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super(listener);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.serverCall = serverCall;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.metadata = metadata;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public void onHalfClose() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.onHalfClose();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (RuntimeException ex) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handleException(ex, serverCall, metadata);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw ex;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public void onReady() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.onReady();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (RuntimeException ex) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handleException(ex, serverCall, metadata);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw ex;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private void handleException(RuntimeException exception, ServerCall<ReqT, RespT> serverCall, Metadata metadata) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (exception instanceof IllegalArgumentException) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; serverCall.close(Status.INVALID_ARGUMENT.withDescription(exception.getMessage()), metadata);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; serverCall.close(Status.UNKNOWN, metadata);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}

绝地无双

gRPC 不会传播错误。来自官方文档-使用给定原因创建 Status 的派生实例。但是,原因不会从服务器传输到客户端。如果您想将自定义信息从服务器传递到客户端,那么您有几个选择 -使用元数据将错误信息从服务器传播到客户端用于google.rpc.Status传递错误详细信息repeated google.protobuf.Any details您需要在这两种情况下捕获异常,准备一条错误消息,并将其发送回客户端。我写了一篇关于gRPC 错误处理的详细博客文章。

江户川乱折腾

启动器的最新版本集成了 spring 验证支持。如果验证失败,它返回 INVALID_ARGUMENT。披露:我是这个启动器的创建者。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java