官网地址:https://docs.spring.io/spring-cloud-commons/reference/spring-cloud-commons/loadbalancer.html
【1】概述
Spring Cloud LoadBalancer是由SpringCloud官方提供的一个开源的、简单易用的客户端负载均衡器
,它包含在SpringCloud-commons中用它来替换了以前的Ribbon组件
。相比较于Ribbon,SpringCloud LoadBalancer不仅能够支持RestTemplate,还支持WebClient(WeClient是Spring Web Flux中提供的功能,可以实现响应式异步请求)
LB负载均衡(Load Balance)是什么
简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用),常见的负载均衡有软件Nginx,LVS,硬件 F5等
loadbalancer本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。
LoadBalancer 在工作时分成两步:
-
第一步,先选择ConsulServer从服务端查询并拉取服务列表,知道了它有多个服务(上图3个服务),这3个实现是完全一样的,默认轮询调用谁都可以正常执行。
-
第二步,按照指定的负载均衡策略从server取到的服务注册列表中由客户端自己选择一个地址,所以LoadBalancer是一个客户端的负载均衡器。
Spring Cloud LoadBalancer 集成使用
为了简化Spring Cloud LoadBalancer的使用,Spring Cloud 提供了ReactorLoadBalancerExchangeFilterFunction
(可与WebClient
配合使用)和BlockingLoadBalancerClient
(可与RestTemplate
和RestClient
一起工作)。更多详细信息及使用示例,请参阅以下章节:
-
Spring RestTemplate作为LoadBalancer客户端
在这一节中,我们将探讨如何将RestTemplate
用作负载均衡客户端,利用BlockingLoadBalancerClient
实现服务间的调用负载均衡。 -
Spring RestClient作为LoadBalancer客户端
这一章节会介绍RestClient
与BlockingLoadBalancerClient
结合使用的方法,展示如何通过这种方式实现对后端服务的负载均衡调用。 -
Spring WebClient作为LoadBalancer客户端
在此部分,我们将讲解如何将WebClient
与ReactorLoadBalancerExchangeFilterFunction
配合使用,以实现非阻塞、响应式的负载均衡调用。 -
Spring WebFlux WebClient与ReactorLoadBalancerExchangeFilterFunction的结合使用
本章节将深入讨论WebFlux
框架下的WebClient
如何与ReactorLoadBalancerExchangeFilterFunction
协同工作,实现高效、响应式的负载均衡机制。
两种主要的工具:ReactorLoadBalancerExchangeFilterFunction 和 BlockingLoadBalancerClient,分别适用于响应式编程和阻塞式编程场景。
【2】Spring RestTemplate as a LoadBalancer Client应用实践
pom依赖:
<!--loadbalancer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
你可以配置一个RestTemplate
来使用负载均衡客户端。要创建一个负载均衡的RestTemplate
,需要创建一个带有@Bean
注解的RestTemplate
实例,并使用@LoadBalanced
限定符,如下例所示:
@Configuration
public class MyConfiguration {
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
public class MyClass {
@Autowired
private RestTemplate restTemplate;
public String doOtherStuff() {
String result = restTemplate.getForObject("http://stores/stores", String.class);
return result;
}
}
这意味着,在你的Spring配置类中,可以通过定义一个带有
@Bean
和@LoadBalanced
注解的方法来生成一个RestTemplate
实例。这样做的结果是,该RestTemplate
实例将自动集成Spring Cloud LoadBalancer的功能,能够智能地在多个服务实例之间进行请求分发,实现负载均衡的效果。这种方法特别适用于基于Spring的微服务架构,使得服务间的调用更加健壯和高效。
如下图所示,当服务实例拥大于等于2时,将会实现轮询效果:
【3】编码使用DiscoveryClient动态获取所有上线的服务列表
这里自动注入DiscoveryClient来获取注册中心的服务实例列表:
@Resource
private DiscoveryClient discoveryClient;
@GetMapping("/consumer/discovery")
public String discovery()
{
// 获取所有服务实例
List<String> services = discoveryClient.getServices();
for (String element : services) {
System.out.println(element);
}
System.out.println("===================================");
//获取指定名字服务实例
List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
for (ServiceInstance element : instances) {
System.out.println(element.getServiceId()+"\t"+element.getHost()+"\t"+element.getPort()+"\t"+element.getUri());
}
return instances.get(0).getServiceId()+":"+instances.get(0).getPort();
}
【4】切换负载均衡算法
默认使用的ReactiveLoadBalancer 实现是RoundRobinLoadBalancer(轮询负载均衡器)。如果你想为某些特定服务或者所有服务切换到不同的负载均衡实现,可以利用自定义的负载均衡配置机制。
例如,下面的配置可以通过@LoadBalancerClient注解切换到使用RandomLoadBalancer(随机负载均衡器):
public class CustomLoadBalancerConfiguration {
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
修改RestTemplateConfig如下所示:
@Configuration
@LoadBalancerClient(value = "cloud-payment-service",configuration = RestTemplateConfig.class)
public class RestTemplateConfig
{
@Bean
@LoadBalanced //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
}