前面章节介绍了 LoadBalancer 的简单用法,以及怎样去自定义配置 LoadBalancer 的负载均衡算法。本章节将介绍 LoadBalancer 怎样与 RestTemplate、WebClient 和 WebFlux 进行集成。
您可以为 RestTemplate 配置负载均衡能力。要创建具有负载均衡的 RestTemplate,则需要在创建 RestTemplate @Bean 时使用 @LoadBalanced 注解,如下所示:
(1)创建 @Configuration 配置类,用于配置 RestTemplate 实例,该实例上面需要指定 @LoadBalanced 注解。代码如下:
@Configuration public class MyConfiguration { @LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
(2)客户端,使用 @Autowired 注解注入我们配置的 RestTemplate 实例,然后调用目标服务。代码如下:
public class MyClass { @Autowired private RestTemplate restTemplate; public String doOtherStuff() { String results = restTemplate.getForObject("http://stores/stores", String.class); return results; } }
注意:
RestTemplate bean 不再通过自动配置创建,而是需要自己手动创建它。
RestTemplate 的 getForObject() 方法的 URI 需要使用虚拟主机名(即服务名,而不是主机名或IP地址),BlockingLoadBalancerClient 用于创建完整的物理地址。
要使用具有负载均衡功能的 RestTemplate,您需要在类路径中包含负载均衡的实现。因此,需要将 Spring Cloud LoadBalancer 启动器添加到您的项目中以便使用它。maven 依赖如下:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
注意,在上面的 spring-cloud-starter-netflix-eureka-client 依赖的 pom.xml 文件中已经添加了 LoadBalancer 的依赖,如下:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> <version>3.0.1</version> <scope>compile</scope> </dependency>
WebClient 是从 Spring WebFlux 5.0 版本开始提供的一个非阻塞的基于响应式编程的进行 Http 请求的客户端工具。它的响应式编程的基于 Reactor 的,WebClient 中提供了标准 Http 请求方式对应的 get、post、put、delete 等方法,可以用来发起相应的请求。
我们也可以为 WebClient 配置自动使用负载均衡器能力的 HTTP 客户端工具。要创建具有负载均衡能力的 WebClient,请先创建 WebClient.Builder @Bean 并使用 @LoadBalanced 注解进行修饰。如下所示:
(1)引入 maven 依赖,如下:
<!-- 引入 webflux 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
(2)创建 @Configuration 配置类,在该类中创建 WebClient.Builder 实例,并且在 WebClient.Builder @Bean 上面添加 @LoadBalanced 注解开启负载均衡能力。代码如下:
@Configuration public class MyConfiguration { @Bean @LoadBalanced public WebClient.Builder loadBalancedWebClientBuilder() { return WebClient.builder(); } }
(3)客户端,使用 @Autowired 注解注入 WebClient.Builder 的实例,然后使用它调用目标服务。代码如下:
@Component public class MyClass { @Autowired private WebClient.Builder clientBuilder; public void demo() { System.out.println("clientBuilder = " + clientBuilder); // 如果你要实现负载均衡,调用地址不能写具体主机地址 // 需要将主机地址替换成对于服务的服务名,即 spring.application.name 指定的值 // 你也可以到 Eureka server 中去查看 String url = "http://USER/info"; for(int i = 0; i < 21; i++) { WebClient.ResponseSpec responseSpec = clientBuilder.baseUrl(url) .build().method(HttpMethod.GET) // post请求 .retrieve(); // 请求结果的方法 // 将结果转换为相应的类型,这是String,直接返回即可 Mono<String> mono = responseSpec.bodyToMono(String.class); String response = mono.block(); System.out.println(response); } } }
运行客户端,结果如下:
clientBuilder = org.springframework.web.reactive.function.client.DefaultWebClientBuilder@7791ff50 From user2 - Thu Apr 15 13:30:02 CST 2021 From user3 - Thu Apr 15 13:30:03 CST 2021 From user1 - Thu Apr 15 13:30:03 CST 2021 ... From user1 - Thu Apr 15 13:30:12 CST 2021 From user2 - Thu Apr 15 13:30:13 CST 2021 From user3 - Thu Apr 15 13:30:13 CST 2021 From user1 - Thu Apr 15 13:30:13 CST 2021