如何在Project Reactor中获取下次重试前的退避时长?
在Project Reactor 3.6+中获取重试退避时长的方法
问题描述
此前使用已废弃的reactor.retry.Retry类时,可通过ctx.backoff().seconds获取下次重试的退避时长:
var myFlux = Flux.of(...) myFlux.retry(Retry .anyOf(TimeoutException.class) .exponentialBackoff(Duration.ofSeconds(1), Duration.ofSeconds(5)).retryMax(5) .doOnRetry(ctx -> { var e = (TimeoutException) ctx.exception(); var secondsToWaitBeforeNextRetry = ctx.backoff().seconds; log.info("Will retry again in roughly {} s", secondsToWaitBeforeNextRetry); }) )
但官方建议改用reactor.util.retry.RetryBackoffSpec后,找不到等价的获取方式,现有转换后的代码中需要补充获取退避时长的逻辑:
var myFlux = Flux.of(...) myFlux.retryWhen(RetryBackoffSpec.backoff(5, Duration.ofSeconds(1)).maxBackoff(Duration.ofSeconds(5)) .filter(TimeoutException.class::isAssignableFrom) .doBeforeRetry(signal -> { var e = (TimeoutException) signal.exception(); var secondsToWaitBeforeNextRetry = // TODO What to write here? log.info("Will retry again in roughly {} s", secondsToWaitBeforeNextRetry); }) )
解决方案
可以通过RetrySignal获取RetryContextView,再调用其backoff()方法拿到退避时长,具体代码修改如下:
var myFlux = Flux.of(...) myFlux.retryWhen(RetryBackoffSpec.backoff(5, Duration.ofSeconds(1)) .maxBackoff(Duration.ofSeconds(5)) .filter(TimeoutException.class::isAssignableFrom) .doBeforeRetry(signal -> { var e = (TimeoutException) signal.exception(); // 获取退避时长并转换为秒 var backoffDuration = signal.context().backoff(); var secondsToWaitBeforeNextRetry = backoffDuration.getSeconds(); log.info("Will retry again in roughly {} s", secondsToWaitBeforeNextRetry); }) )
signal.context()返回RetryContextView,这是新API中承载重试上下文信息的类RetryContextView.backoff()直接返回本次重试的退避Duration,可以通过getSeconds()、toMillis()等方法转换为需要的时间单位
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

