如何解决处理 gRPC 中的异常
我在让我的 gRPC 端点按预期工作时遇到了一些问题,我已经简化了我的代码来说明我遇到的问题。本质上,我无法让 exceptionally
主体中的代码执行,我不知道为什么,它似乎总是返回带有代码 UNKNowN
的状态,但我期待它返回INVALID_ARGUMENT
因为这就是我在 GetNamesService
类中的内容。异常子句中的 System.out.println
也不打印。
public class GrpcService extends GrpcServiceImplBase {
private final GetNamesService getNamesService;
public GrpcService(GetNamesService getNamesService) {
this.getNamesService = getNamesService;
}
@Override
public void getNames(NameRequest request,StreamObserver<NameResponse> responSEObserver) {
getNamesService.getNames(request)
.thenAccept(r -> {
responSEObserver.onNext(r);
responSEObserver.onCompleted();
})
.exceptionally(t -> {
System.out.println("About to handle the exception");
responSEObserver.onError(handleException(t));
});
}
private StatusRuntimeException handleException(Throwable t) {
if (t instanceof CompletionException) {
return handleException(t.getCause());
}
if (t instanceof StatusRuntimeException) {
var statusException = (StatusRuntimeException) t;
return statusException;
}
return Status.UNKNowN.withDescription(t.getMessage()).asRuntimeException();
}
}
public class GetNamesService {
public CompletionStage<NameResponse> getNames(NameRequest request) {
// Just throwing an exception to try and get error handling to work
throw Status.INVALID_ARGUMENT
.withDescription("Invalid request")
.asRuntimeException();
}
}
解决方法
在这块流畅的代码中:
getNamesService.getNames(request)
.thenAccept(r -> {
responseObserver.onNext(r);
responseObserver.onCompleted();
})
.exceptionally(t -> {
System.out.println("About to handle the exception");
responseObserver.onError(handleException(t));
});
如果整个块都运行,则调用 getNamesService.getNames(request)
,并且该方法的返回值是一个包含 thenAccept
方法的对象。然后调用该方法,并返回一个包含 exceptionally
方法的对象。最后,调用 exceptionally
方法。
这里没有魔法。这只是普通的旧 Python。该链之所以有效,是因为每个方法调用都会返回一个对象,该对象包含一个方法,使得链中的下一个方法调用有效。如果链中的方法抛出异常而不是返回包含链中下一个方法的对象,则不会执行链的其余部分。
当调用 getNamesService.getNames(request)
并抛出异常时,链中剩余的方法 thenAccept
和 exceptionally
不会被执行,因此没有理由期望 {{块中的 1}} 将被调用。
对于您提供的代码,System.out.println
总是抛出异常,因此上面复杂的代码块在功能上等同于:
getNamesService.getNames(request)
,
问题是您正在混合调用约定。 getNames()
返回一个 CompletionStage,因此调用代码处理它正在使用的期货,但随后会引发异常。
如果您将 GetNamesService.getNames()
的实现更改为使未来失败而不是抛出,那么它应该可以解决问题:
public CompletionStage<NameResponse> getNames(NameRequest request) {
// Just failing the future to try and get error handling to work
CompletableFuture<NameResponse> f = new CompletableFuture<>();
f.completeExceptionally(Status.INVALID_ARGUMENT
.withDescription("Invalid request")
.asRuntimeException());
return f;
}
或者,您可以在 GrpcService.getNames()
中捕获异常。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。