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。```javaspring:application:name: mall-user-loadbalancer-democloud:nacos:discovery:server-addr: 127.0.0.1:8848# 不使用ribbonloadbalancer:ribbon:enabled: false
原理:默认情况下,如果同时拥有 RibbonLoadBalancerClient 和 BlockingLoadBalancerClient,为了保持向后兼容性,将使用RibbonLoadBalancerClient。要覆盖它,可以设置 spring.cloud.loadbalancer.ribbon.enabled 属性为false。
2.2 配置RestTemplate
@Configurationpublic class RestConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}}
2.3 使用RestTemplate
@RestController@RequestMapping("/user")public class UserController {@Autowiredprivate 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
@Autowiredprivate ReactorLoadBalancerExchangeFilterFunction lbFunction;@RequestMapping(value = "/findOrderByUserId3/{id}")public Mono<R> findOrderByUserIdWithWebFlux(@PathVariable("id") Integer id) {String url = "http://mall-order/order/findOrderByUserId/"+id;//基于WebClient+webFluxMono<R> result = WebClient.builder().filter(lbFunction).build().get().uri(url).retrieve().bodyToMono(R.class);return result;}
