Spring Cloud LoadBalancer 是 Spring Cloud 组件库中提供的一款服务负载均衡组件,它基于 Ribbon 实现了负载均衡的功能,为服务消费者提供了自动化的服务发现和负载均衡的能力。
一、服务发现
服务发现是指服务提供者将自己注册到服务注册中心,服务消费者通过服务注册中心获取可用的服务列表,并通过负载均衡算法选择一台可用的服务提供者进行调用。Spring Cloud 中的服务发现采用的是 Eureka 或 Consul 等服务注册中心实现。
Spring Cloud LoadBalancer 提供了两种服务发现的方式:基于 Spring Cloud 服务注册中心的服务发现和基于自定义服务列表的服务发现。
1. 基于 Spring Cloud 服务注册中心的服务发现
在基于 Spring Cloud 服务注册中心的服务发现中,服务消费者通过 Spring Cloud 的服务发现客户端从服务注册中心获取可用的服务列表。Spring Cloud LoadBalancer 通过自定义 Ribbon 的 ServerList 实现从服务注册中心获取可用的服务列表,并通过 Ribbon 的负载均衡算法选择一台可用的服务提供者进行调用。
以基于 Eureka 的服务注册中心为例,服务消费者需要添加如下依赖:
代码语言:javascript复制<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
同时需要在配置文件中添加如下配置:
代码语言:javascript复制spring:
application:
name: service-consumer
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
在服务消费者的业务逻辑中,需要使用 @LoadBalanced
注解将 RestTemplate 注册为负载均衡的 RestTemplate,如下所示:
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
这样,当服务消费者调用服务提供者的接口时,可以直接使用服务提供者的应用名作为 URL,Spring Cloud LoadBalancer 会自动从服务注册中心获取可用的服务列表,并通过负载均衡算法选择一台可用的服务提供者进行调用,如下所示:
代码语言:javascript复制@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/hello")
public String hello() {
return restTemplate.getForObject("http://service-provider/hello", String.class);
}
}
2. 基于自定义服务列表的服务发现
在基于自定义服务列表的服务发现中,服务消费者需要手动指定可用的服务列表,并通过 Spring Cloud LoadBalancer 提供的负载均衡算法选择一台可用的服务提供者进行调用。
以基于 Ribbon 的负载均衡算法为例,服务消费者需要添加如下依赖:
代码语言:javascript复制<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
在服务消费者的业务逻辑中,可以使用 LoadBalancerClient 手动指定可用的服务列表,并通过负载均衡算法选择一台可用的服务提供者进行调用,如下所示:
代码语言:javascript复制@RestController
public class ConsumerController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/hello")
public String hello() {
ServiceInstance serviceInstance = loadBalancerClient.choose("service-provider");
String url = "http://" serviceInstance.getHost() ":" serviceInstance.getPort() "/hello";
return restTemplate.getForObject(url, String.class);
}
}