我遇到了一个非常奇怪的问题:基本上,我正在用Java实现服务器流式grpc客户端,并且我将微配置文件用作库/结构。当涉及到自动重试和回退时,Microprofiles具有非常方便的拦截器,但是它依赖于在带有拦截器注释的函数中引发的异常,否则不会触发重试。
对于一元grpc调用,这很好,它的工作原理与普通REST调用非常相似。但是,当使客户端成为grpc服务器端流时,protobuf将创建它自己的线程并请求回调以处理onNext,onError和onCompleted。因此,在流范围内调用onError时,抛出的任何异常都不会发送回用于启动流的任何函数,因此不会引发任何异常来触发@Retry。
无法更改异步流的处理方式,也无法更改@Retry的触发方式。 Grpc是生成的代码,并且@Retry触发器基于微配置文件库。
示例:
@Retry(
retryOn = {IOException.class, TimeoutException.class, StatusRuntimeException.class},
maxDuration = 10,
durationUnit = ChronoUnit.SECONDS,
maxRetries = 1,
delay = 10,
delayUnit = ChronoUnit.SECONDS
)
public void subscribeToLocations() {
// --> Throwing an exception here triggers the @Retry <--
SubscribeRequest locSubscribeRequest = SubscribeRequest.newBuilder().build();
streamObserver = grpcStreamHandler();
grpcBlockingstub.subscribeServerStreaming(locSubscribeRequest, streamObserver); // Can't change this.
}
private StreamObserver<SubscribeResponse> grpcStreamHandler() {
return new StreamObserver<SubscribeResponse>() {
@Override
public void onNext(SubscribeResponse value) {
// Handle grpc response
}
@Override
public void onError(Throwable t) {
// --> ERROR: Here, it should trigger the @Retry somehow. <--
}
@Override
public void onCompleted() {
// Handle oncomplete
}
};
}
我试图找到解决方案的时间超过了我希望承认的时间,但是我仍然茫然。有没有一种方法可以在一个范围内引发一个异常,而该范围又在另一个范围内终止?还有其他解决方法吗?
您在此处混合了同步操作和异步操作,因此您需要为您明确定义什么是“成功”,并且不需要重试。它可能取决于您的逻辑,很少有流式传输选项:
一旦定义了“成功”规则,就可以将订阅包装到Future中,并等待提供的超时解决该订阅。如果未解决,则从原始调用中引发Exception。