Java Webflux Webclient使用不同的URL重试
我正在使用webclient进行rest调用,我需要的是,如果主URL第n次失败,请在辅助URL上进行下一次重试。请在下面找到我正在使用的逻辑的示例代码。但是,一旦他Java Webflux Webclient使用不同的URL重试,java,spring,spring-boot,spring-webflux,Java,Spring,Spring Boot,Spring Webflux,我正在使用webclient进行rest调用,我需要的是,如果主URL第n次失败,请在辅助URL上进行下一次重试。请在下面找到我正在使用的逻辑的示例代码。但是,一旦他客户机被创建,我们似乎就无法更改URL,即使我更改了URL,它也不会生效,并且仍然会向初始URL发出请求 ClientHttpConnector connector;//initiate WebClient webClient = WebClient.builder().clientConnector(connector).buil
客户机
被创建,我们似乎就无法更改URL,即使我更改了URL,它也不会生效,并且仍然会向初始URL发出请求
ClientHttpConnector connector;//initiate
WebClient webClient = WebClient.builder().clientConnector(connector).build();
WebClient.RequestBodyUriSpec client = webClient.post();
client.uri("http://primaryUrl/").body(BodyInserters.fromObject("hi")).retrieve().bodyToMono(String.class).retryWhen(Retry.anyOf(Exception.class)
.exponentialBackoff(Duration.ofSeconds(2), Duration.ofSeconds(10)).doOnRetry(x ->
{
if (x.iteration() == 2) {
client.uri("http://fail_over_url/");//this does not work
}
})
.retryMax(2)).subscribe(WebClientTest::logCompletion, WebClientTest::handleError);
有没有办法在重试周期中间更改URL
但似乎一旦客户端创建,我们就无法更改URL
你不能——它是不可变的
即使我更改了URL,它也不会生效
您实际上并没有更改URL。看看uri()
方法-它返回一个新实例,并设置了一个uri。由于您没有对该新实例执行任何操作,因此不会发生任何事情(如预期的那样)
我可能建议的方法是创建一个单独的方法来形成并返回您的基本WebClient
publisher:
private Mono<String> fromUrl(String url) {
return WebClient.builder().clientConnector(connector).build()
.post()
.body(BodyInserters.fromValue("hi"))
.uri(url)
.retrieve()
.bodyToMono(String.class);
}
…它将尝试/400
3次,然后尝试/500
5次,然后尝试/200
最多7次(但除非它关闭,否则第一次尝试时当然会返回。)
请注意,上面的示例使用了最新版本的reactor core,它内置了重试功能,而不是reactor插件中的重试功能。将其转换为reactor插件功能应该相当简单
这并不是严格地在相同的重试周期中更改URL,而是将请求链接在一起,并为每个请求配置重试次数。然后,这允许您在不同的URL上设置不同的重试策略,如果您不一定希望重试从上一点“继续”,这将是有利的(例如,对于一个新的URL,将回退设置为1秒是有意义的)。您使用的是哪种版本的Reactor+插件?由于静态引用和错误的方法签名,我的ide中出现了大量错误。另外,
connector
来自fromUrl的哪个位置,它是否不需要传入,或者您是否假设它在类中是全局的?@123最新版本的reactor core-不再需要附加组件,包含所有内置的重试功能。(假设连接器是全局的,因为问题并没有在任何地方实例化它,但如果它不是全局的,就很容易改变。)啊,实际上在测试项目中两者都有。看起来额外的是第一个在导入,所以需要完整的路径。此外,我认为OP仍在使用额外功能,因为它们使用的是anyOf
,这不在核心重试@123中,这是一个很好的观点-这将教会我如何快速。。。我会在回答中澄清这一点。谢谢@MichaelBerry,完美的答案。
fromUrl("https://httpstat.us/400").retryWhen(Retry.backoff(2, Duration.ofSeconds(1)))
.onErrorResume(t -> Exceptions.isRetryExhausted(t), t -> fromUrl("https://httpstat.us/500").retryWhen(Retry.backoff(5, Duration.ofSeconds(1))))
.onErrorResume(t -> Exceptions.isRetryExhausted(t), t -> fromUrl("https://httpstat.us/200").retryWhen(Retry.backoff(7, Duration.ofSeconds(1))))