这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战
本系列代码地址:github.com/JoJoTec/spr…
要想实现我们上一节中提到的:
- 需要在重试以及断路中加一些日志,便于日后的优化
- 需要定义重试的 Exception,并且与断路器相结合,将非 2xx 的响应码也封装成特定的异常
- 需要在断路器相关的 Operator 中增加类似于 FeignClient 中的负载均衡的数据更新,使得负载均衡更加智能
我们需要将 resilience4j 本身提供的粘合库做一些改造,其实主要就是对 resilience4j 实现的 project reactor 的 Operator 进行改造。
关于断路器的改造
首先,WebClient 的返回对象只可能是 ClientResponse
类型,所以我们这里改造出来的 Operator 不必带上形参,只需要针对 ClientResponse 即可,即:
1 | csharp复制代码public class ClientResponseCircuitBreakerOperator implements UnaryOperator<Publisher<ClientResponse>> { |
在原有的断路器逻辑中,我们需要加入针对 GET 方法以及之前定义的可以重试的路径匹配配置可以重试的逻辑,这需要我们拿到原有请求的 URL 信息。但是 ClientResponse 中并没有暴露这些信息的接口,其默认实现 DefaultClientResponse(我们只要没有自己给 WebClient 加入特殊的改造逻辑,实现都是 DefaultClientResponse) 中的 request()
方法可以获取请求 HttpRequest,其中包含 url 信息。但是这个类还有方法都是 package-private 的,我们需要反射出来:
ClientResponseCircuitBreakerSubscriber
1 | php复制代码private static final Class<?> aClass; |
之后,在获取到 ClientResponse 之后记录断路器的逻辑中,需要加入上面提到的关于重试的改造,以及负载均衡器的记录:
ClientResponseCircuitBreakerSubscriber
1 | scss复制代码protected void hookOnNext(ClientResponse clientResponse) { |
同样的,在原有的完成,取消还有失败的记录逻辑中,也加上记录负载均衡数据:
ClientResponseCircuitBreakerSubscriber
1 | scss复制代码@Override |
粘合 WebClient 与 resilience4j 的同时覆盖重试逻辑
由于前面的断路器中,我们针对可以重试的非 2XX 响应封装成为 WebClientResponseException。所以在重试器中,我们需要加上针对这个异常的重试。
同时,需要将重试器放在负载均衡器之前,因为每次重试,都要从负载均衡器中获取一个新的实例。同时,断路器需要放在负载均衡器之后,因为只有在这个之后,才能获取到本次调用的实例,我们的的断路器是针对实例方法级别的:
WebClientDefaultConfiguration.java
1 | ini复制代码@Bean |
这样,我们就实现了我们封装的基于配置的 WebClient
微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer:
本文转载自: 掘金