Spring负载均衡LoadBalancer使用详解
作者:morris131
LoadBalancer
Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器, 用来替代Ribbon。
Spring官方提供了两种客户端都可以使用loadbalancer:
- RestTemplate:Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。默认情况下,RestTemplate默认依赖jdk的HTTP连接工具。
- WebClient:从Spring WebFlux 5.0版本开始提供的一个非阻塞的基于响应式编程的进行Http请求的客户端工具。它的响应式编程的基于Reactor的。WebClient中提供了标准Http请求方式对应的get、post、put、delete等方法,可以用来发起相应的请求。
RestTemplate整合LoadBalancer
引入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。
默认情况下,如果同时拥有RibbonLoadBalancerClient和BlockingLoadBalancerClient,为了保持向后兼容性,将使用RibbonLoadBalancerClient。
要覆盖它,可以设置spring.cloud.loadbalancer.ribbon.enabled属性为false。
spring: application: name: user-service cloud: nacos: discovery: server-addr: 127.0.0.1:8848 # 不使用ribbon,使用loadbalancer loadbalancer: ribbon: enabled: false
使用@LoadBalanced注解修饰RestTemplate,开启客户端负载均衡功能
package com.morris.user.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class RestConfig { /** * 默认的RestTemplate,不带负载均衡 * @return */ @Bean public RestTemplate restTemplate() { return new RestTemplate(); } /** * 有负责均衡能力的RestTemplate * @return */ @Bean @LoadBalanced public RestTemplate restTemplate2() { return new RestTemplate(); } }
RestTemplate的使用:
package com.morris.user.controller; import com.morris.user.entity.Order; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import java.util.Arrays; import java.util.List; @RestController @RequestMapping("user") public class RestTemplateController { @Resource private RestTemplate restTemplate; @Resource private RestTemplate restTemplate2; @GetMapping("findOrderByUserId") public List<Order> findOrderByUserId(Long userId) { Order[] orders = restTemplate.getForObject("http://127.0.0.1:8020/order/findOrderByUserId?userId=", Order[].class, userId); return Arrays.asList(orders); } @GetMapping("findOrderByUserId2") public List<Order> findOrderByUserId2(Long userId) { Order[] orders = restTemplate2.getForObject("http://order-service/order/findOrderByUserId?userId=", Order[].class, userId); return Arrays.asList(orders); } }
WebClient整合LoadBalancer
引入依赖webflux,WebClient位于webflux内:
<!-- 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>
同样需要在配置文件中禁用ribbon:
spring: application: name: user-service cloud: nacos: discovery: server-addr: 127.0.0.1:8848 # 不使用ribbon,使用loadbalancer loadbalancer: ribbon: enabled: false
使用@LoadBalanced注解修饰WebClient.Builder,开启客户端负载均衡功能
package com.morris.user.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.function.client.WebClient; @Configuration public class WebClientConfig { @Bean WebClient.Builder webClientBuilder() { return WebClient.builder(); } @Bean @LoadBalanced WebClient.Builder webClientBuilder2() { return WebClient.builder(); } }
WebClient负载均衡的使用:
package com.morris.user.controller; import com.morris.user.entity.Order; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import javax.annotation.Resource; import java.util.Arrays; import java.util.List; @RestController @RequestMapping("user2") public class WebClientController { @Resource private WebClient.Builder webClientBuilder; @Resource private WebClient.Builder webClientBuilder2; @GetMapping("findOrderByUserId1") public Mono<List<Order>> findOrderByUserId1(Long userId) { return webClientBuilder.build().get().uri("http://127.0.0.1:8020/order/findOrderByUserId?userId=" + userId) .retrieve().bodyToMono(Order[].class).map(t -> Arrays.asList(t)); } @GetMapping("findOrderByUserId2") public Mono<List<Order>> findOrderByUserId2(Long userId) { return webClientBuilder2.build().get().uri("http://order-service/order/findOrderByUserId?userId=" + userId) .retrieve().bodyToMono(Order[].class).map(t -> Arrays.asList(t)); } }
原理:底层会使用ReactiveLoadBalancer
WebClient设置Filter实现负载均衡
与RestTemplate类似,@LoadBalanced注解的功能是通过SmartInitializingSingleton实现的。
SmartInitializingSingleton是在所有的bean都实例化完成之后才会调用的,所以在bean的实例化期间使用@LoadBalanced修饰的WebClient是不具备负载均衡作用的,比如在项目的启动过程中要使用调用某个微服务,此时WebClient是不具备负载均衡作用的。
可以通过手动为WebClient设置Filter实现负载均衡能力。
@Bean WebClient.Builder webClientBuilder3(ReactorLoadBalancerExchangeFilterFunction lbFunction) { return WebClient.builder().filter(lbFunction); }
到此这篇关于Spring负载均衡LoadBalancer使用详解的文章就介绍到这了,更多相关Spring负载均衡LoadBalancer内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!