Spring Cloud LoadBalancer
Spring Cloud LoadBalancer 是 Spring Cloud 官方提供的客户端负载均衡器,用来代替 Ribbon
Spring 官方提供了两种负载均衡的客户端:
- RestTemplate:Spring 提供的用与访问 Rest 服务的客户端,RestTemplate 提供了多重便捷访问远程 Http 服务的方法,提高客户端的编写效率;默认情况下,RestTemplate 依赖 JDK 的 HTTP 链接工具
- WebClient:Spring WebFlux 5.0 版本开始提供的一个非阻塞的基于响应式变成的进行 Http 请求的客户端工具;它的响应式编程基于 Reactor;WebClient 提供了标准 Http 请求方式对应的 get、post、put、delete 等方法,可以用来发起相应的请求
RestTemplate 整合 LoadBalancer
引入依赖
<!-- LoadBalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- 提供了RestTemplate支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos服务注册与发现 移除ribbon支持-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
注:nacos-discovery 中引入了 ribbon,需要移除 ribbon 的包;若不移除,也可以在 yml 中配置不使用 ribbon
spring:
application:
name: mall-user-loadbalancer-demo
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 不使用ribbon
loadbalancer:
ribbon:
enabled: false
原理:默认情况下,若同时拥有 RibbonLoadBalancerClient 和 BlockingLoadBalancerClient,为保持向后兼容性,将使用 RibbonLoadBalancerClient;要覆盖它,可以设置 spring.cloud.loadbalancer.ribbon.enabled 属性为 false
使用@LoadBalanced 注解配置 RestTemplate
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
使用:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
String url = "http://mall-order/order/findOrderByUserId/"+id;
R result = restTemplate.getForObject(url,R.class);
return result;
}
}
WebClient 整合 LoadBalancer
引入依赖
<!-- LoadBalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- webflux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- nacos服务注册与发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
配置 WebClient 作为负载均衡器的 client
@Configuration
public class WebClientConfig {
@LoadBalanced
@Bean
WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
@Bean
WebClient webClient() {
return webClientBuilder().build();
}
}
使用:
@Autowired
private WebClient webClient;
@RequestMapping(value = "/findOrderByUserId2/{id}")
public Mono<R> findOrderByUserIdWithWebClient(@PathVariable("id") Integer id) {
String url = "http://mall-order/order/findOrderByUserId/"+id;
//基于WebClient
Mono<R> result = webClient.get().uri(url)
.retrieve().bodyToMono(R.class);
return result;
}
原理:底层会使用 ReactiveLoadBalancer
引入 webFlux:
@Autowired
private ReactorLoadBalancerExchangeFilterFunction lbFunction;
@RequestMapping(value = "/findOrderByUserId3/{id}")
public Mono<R> findOrderByUserIdWithWebFlux(@PathVariable("id") Integer id) {
String url = "http://mall-order/order/findOrderByUserId/"+id;
//基于WebClient+webFlux
Mono<R> result = WebClient.builder()
.filter(lbFunction)
.build()
.get()
.uri(url)
.retrieve()
.bodyToMono(R.class);
return result;
}