Spring Cloud 的 Hoxton.M2 版本整合了新的 LoadBalancer 实现来替代 Ribbon 实现版本。
在 Spring Cloud 中提供了客户端负载均衡器的抽象和实现。对于负载均衡机制,添加了 ReactiveLoadBalancer 接口,并为其提供了基于 Round-Robin(循环)和 Random(随机)的实现。分别为:
org.springframework.cloud.loadbalancer.core.RandomLoadBalancer 随机算法负载均衡实现
org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer 轮询算法负载均衡实现
下面通过实例来演示 LoadBalancer 的用法。
参考“Netflix Ribbon 简单实例”章节提供的 User 服务,这里将不再赘述。需要注意的是,这里的 User 服务需要注册到 Eureka 注册中心,因此需要在 application.yml 配置文件中添加如下配置:
# 端口不需要指定,通过命令行动态指定 spring: application: name: user # 服务地址 eureka: instance: hostname: localhost # 心跳间隔5s,默认30s。每一个服务配置后,心跳间隔和心跳超时时间会被保存在server端, # 不同服务的心跳频率可能不同,server 端会根据保存的配置来分别探活 lease-renewal-interval-in-seconds: 5 # 心跳超时时间10s,默认90s。从client端最后一次发出心跳后,达到这个时间没有再次发出 # 心跳,表示服务不可用,将它的实例从注册中心移除 lease-expiration-duration-in-seconds: 10 client: service-url: # 注册中心路径,表示我们向这个注册中心注册服务,如果向多个注册中心注册,用“,”进行分隔 defaultZone: http://localhost:8077/eureka
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!-- 省略代码 --> <properties> <java.version>1.8</java.version> <spring-cloud.version>2020.0.1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <!-- 省略代码 --> </project>
上面添加了 Spring Cloud 和 Spring Boot 依赖,以及 Eureka client 依赖。
在该配置文件中指定 Eureka 注册中心地址,以及应用名称和端口。配置如下:
server: port: 8080 spring: application: name: demo eureka: client: serviceUrl: # 指定注册中心 defaultZone: http://localhost:8077/eureka/
创建 RestTemplateConfig 类,用来配置 RestTemplate 类,并且在该类上面添加 @LoadBalanced 注解,该注解用来在 RestTemplate 类上面启用负载均衡功能。代码如下:
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 RestTemplateConfig { // 配置一个 RestTemplate @Bean // 添加该注解后,可以使得 RestTemplate 拥有负载均衡能力 @LoadBalanced public RestTemplate restTemplate() { System.out.println("init RestTemplate"); return new RestTemplate(); } }
创建 Demo1 类,使用 @Autowired 注解注入 RestTemplate 实例,然后使用 RestTemplate 实例调用目标用户服务。代码如下:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @Component public class Demo1 { @Autowired private RestTemplate restTemplate; public void demo() { System.out.println("restTemplate = " + restTemplate); // 如果你要实现负载均衡,调用地址不能写具体主机地址 // 需要将主机地址替换成对于服务的服务名,即 spring.application.name 指定的值 // 你也可以到 Eureka server 中去查看 String url = "http://USER/info"; for(int i = 0; i < 21; i++) { ResponseEntity<String> resp = restTemplate.getForEntity(url, String.class); if(resp.getStatusCode().is2xxSuccessful()) { System.out.println(resp.getStatusCode().value() + " :: " + resp.getBody()); } else { System.out.println(resp.getStatusCode().value() + " :: " + resp.getBody()); } } } }
执行结果如下:
200 :: From user1 - Wed Apr 14 22:52:19 CST 2021 200 :: From user3 - Wed Apr 14 22:52:19 CST 2021 200 :: From user2 - Wed Apr 14 22:52:19 CST 2021 ... 200 :: From user1 - Wed Apr 14 22:52:26 CST 2021 200 :: From user3 - Wed Apr 14 22:52:26 CST 2021 200 :: From user2 - Wed Apr 14 22:52:26 CST 2021 200 :: From user1 - Wed Apr 14 22:52:27 CST 2021 200 :: From user3 - Wed Apr 14 22:52:27 CST 2021 200 :: From user2 - Wed Apr 14 22:52:28 CST 2021
根据上面调用结果可知,LoadBalancer 默认采用的是轮询算法,下一章节将介绍怎样去自定义配置随机算法。