返回

Hoxton-WebFlux-突破重试后依旧访问相同实例的解决方案

见解分享

在《Spring Cloud升级之路 - Hoxton - 7. 后续更新(WebFlux等)》的最后,笔者讲述了Ribbon如何避免重试相同的实例,通过traceId隔离负载均衡的position,但没有考虑在负载均衡过程中,实例列表的更新。

WebFlux 出现背景

在Spring Cloud早期版本,Ribbon被普遍认为是实现负载均衡的最佳实践,但随着Spring Cloud的发展,Ribbon暴露了一些不足。

  • Ribbon只支持HTTP/HTTPS协议的负载均衡,并且不支持服务间的调用,在处理WebFlux时,存在一定的问题。
  • 在WebFlux中,通常需要多次重试才能成功。而在Ribbon中,如果使用了自定义负载均衡器,这些重试请求可能会被路由到相同的实例上。

WebFlux工作原理

WebFlux是Spring Cloud Hoxton中引入的新特性,它解决了Ribbon在处理WebFlux请求时存在的问题。WebFlux的工作原理如下:

  • WebFlux使用随机算法选择第一个实例,并将请求路由到该实例。
  • 如果请求失败,WebFlux会根据用户配置的重试策略,随机选择一个不同的实例,并将请求路由到该实例。
  • WebFlux会一直重试,直到请求成功或者达到用户配置的最大重试次数。

WebFlux与Ribbon对比

WebFlux与Ribbon相比,具有以下优点:

  • 支持更广泛的协议,除了HTTP/HTTPS之外,还支持TCP、UDP等协议。
  • 支持服务间的调用。
  • 具有更好的容错性。

WebFlux使用示例

我们通过一个简单的示例来说明如何使用WebFlux。

在pom.xml文件中,添加以下依赖:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-webflux</artifactId>
  <version>2.2.2.RELEASE</version>
</dependency>

在application.properties文件中,添加以下配置:

spring.cloud.loadbalancer.ribbon.enabled=false
spring.cloud.loadbalancer.webflux.enabled=true

在代码中,使用@LoadBalanced注解来标识需要负载均衡的Bean:

@LoadBalanced
@Bean
public WebClient.Builder webClientBuilder() {
  return WebClient.builder();
}

然后,就可以使用WebClient来发送请求了:

WebClient webClient = webClientBuilder().build();
Mono<String> response = webClient.get()
  .uri("http://my-service/hello")
  .retrieve()
  .bodyToMono(String.class);

WebFlux局限性

WebFlux也存在一些局限性:

  • 不支持所有Ribbon的功能,例如ZoneAvoidanceRule。
  • 在某些情况下,WebFlux的性能可能不如Ribbon。

WebFlux注意事项

在使用WebFlux时,需要注意以下几点:

  • 确保WebFlux与Ribbon的版本兼容。
  • 在使用WebFlux时,需要配置重试策略。
  • 在某些情况下,WebFlux的性能可能不如Ribbon,因此需要进行性能测试。

结语

WebFlux是Spring Cloud Hoxton中引入的新特性,它解决了Ribbon在处理WebFlux请求时存在的问题。WebFlux具有更好的容错性和支持更广泛的协议等优点,但是在使用WebFlux时,也需要注意它的局限性和注意事项。