1. 简介
1.1 认识Load Balancer(LB)
Spring Cloud LoadBalancer 是 Spring Cloud 官方自己提供的客户端负载均衡器, 用来替代 Ribbon。简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)
Spring官方提供了两种负载均衡的客户端:
- RestTemplate:是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 Http 服务的方法,能够大大提高客户端的编写效率。默认情况下,RestTemplate 默认依赖 jdk 的 HTTP 连接工具。
WebClient:是从 Spring WebFlux 5.0 版本开始提供的一个非阻塞的基于响应式编程的进行 Http 请求的客户端工具。它的响应式编程的基于 Reactor的。WebClient 中提供了标准 Http 请求方式对应的 get、post、put、delete 等方法,可以用来发起相应的请求。
1.2 Load Balancer和Ribbon的区别
Ribbon 和 loadbalancer 都是 springcloud 的负载均衡组件。
Ribbon 是 Netflix 开源的基于 HTTP 和 TCP 等协议负载均衡组件,loadBalancer 是 SpringCloud 自己写的,根据服务 id 获取负载均衡器 rpc 地址。
Ribbon 的使用需要代码里手动调用目标服务,loadBalancer 底层原理是默认调用 Ribbon 的实现客户端负载均衡。2. RestTemplate整合LoadBalancer
2.1 引入依赖
```xml
org.springframework.cloud spring-cloud-starter-loadbalancer
如果不移除 ribbon 包,也可以在 yml 中配置不使用 ribbon。
```java
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。
2.2 配置RestTemplate
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.3 使用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;
}
}
原理: 底层会使用 ReactiveLoadBalancer。
2.4 使用WebClient
@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;
}