目录
一、Ribbon目前也进入维护模式
二、spring-cloud-loadbalancer概述
三、spring-cloud-loadbalancer负载均衡解析
1.负载均衡演示案例-理论
2.负载均衡演示案例-实操
按照8001拷贝后新建8002微服务
启动Consul,将8001/8002启动后注册进微服务
Consul数据持久化配置并且注册为Windows服务
方式一:编写脚本的方式
方式二:通过-data-dir进行设置consul持久化目录
消费者-订单80模块修改POM并注册进consul,新增LoadBalancer组件
订单80模块修改Controler并启动80
目前consul上的服务 将order也进行注册
测试
3.负载均衡演示案例-小总结
编码使用DiscoveryClient动态获取所有上线的服务列表
代码解释,修改80微服务的Controller
结合前面实操,负载选择原理小总结
4.负载均衡算法原理
官网算法
默认算法
算法切换
测试
一、Ribbon目前也进入维护模式
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套 客户端 负载均衡的工具。简单的说,Ribbon是Netflix发布的开源项目,主要功能是 提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。
项目状态:维护中...


二、spring-cloud-loadbalancer概述
loadbalancer目前在springcloudcommons下


简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用),常见的负载均衡有软件Nginx,LVS,硬件 F5等
Spring Cloud LoadBalancer是由SpringCloud官方提供的一个开源的、简单易用的 客户端负载均衡器,它包含在SpringCloud-commons中用它来替换了以前的Ribbon组件。相比较于Ribbon,SpringCloud LoadBalancer不仅能够支持RestTemplate,还支持WebClient(WeClient是Spring Web Flux中提供的功能,可以实现响应式异步请求)
Nginx是 服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求,即负载均衡是由服务端实现的。loadbalancer 本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。
三、spring-cloud-loadbalancer负载均衡解析
1.负载均衡演示案例-理论

第一步,先选择ConsulServer从服务端查询并拉取服务列表,知道了它有多个服务(上图3个服务),这3个实现是完全一样的,默认轮询调用谁都可以正常执行。类似生活中求医挂号,某个科室今日出诊的全部医生,客户端你自己选一个。第二步,按照指定的负载均衡策略从server取到的服务注册列表中由客户端自己选择一个地址,所以LoadBalancer是一个 客户端的 负载均衡器。
2.负载均衡演示案例-实操


按照8001拷贝后新建8002微服务
启动Consul,将8001/8002启动后注册进微服务
看到两个service已注册成功, 但是consul的key/value之前配置未进行持久化保存,已经不存在

Consul数据持久化配置并且注册为Windows服务
方式一:编写脚本的方式
- 新建mydata文件夹
- 新建文件consul start.bat后缀为.bat
@echo.服务启动......
@echo off
@sc create Consul binpath= "D:\devSoft\consul_1.17.0_windows_386\consul.exe agent -server -ui -bind=127.0.0.1 -client=0.0.0.0 -bootstrap-expect 1 -data-dir D:\devSoft\consul_1.17.0_windows_386\mydata "
@net start Consul
@sc config Consul start= AUTO
@echo.Consul start is OK......success
@pause



方式二:通过-data-dir进行设置consul持久化目录
consul agent -server -config-dir=E:/consul/config -data-dir=E:/consul/data -bind=127.0.0.1 -bootstrap-expect=1 -ui
-consul agent:启动Consul的代理(agent)进程。Consul代理是Consul服务的核心组件,负责服务注册与发现、健康检查、键值存储等功能。-server:指定此Consul代理以服务器模式运行。在服务器模式下,该代理将参与Raft一致性协议,能够处理集群的选举、日志复制等任务,是Consul集群中不可或缺的一部分。-config-dir=E:/consul/config:指定一个目录,Consul会从该目录中加载额外的配置文件。这些配置文件可以是JSON或HCL格式,用于自定义Consul的行为,如服务定义、ACL策略等。-data-dir=E:/consul/data:指定一个目录,Consul将在此目录中存储其运行所需的数据,包括服务注册信息、健康检查的状态、键值存储的数据以及Raft日志和快照等。这个目录对于Consul的数据持久化至关重要。-bind=127.0.0.1:指定Consul代理绑定的IP地址。在这个例子中,Consul被配置为仅监听本地回环地址(127.0.0.1),这意味着它不会接受来自外部网络的连接请求,增强了安全性。这通常用于开发或测试环境。-bootstrap-expect=1:这是一个引导模式配置,指定了Consul期望在集群中看到的服务器节点数。在这个例子中,-bootstrap-expect=1 表示这是一个单节点集群的配置。由于集群中只有一个节点,Consul将立即进入领导者模式,无需等待其他节点的加入。-ui:启用Consul的内置Web UI。通过Web UI,用户可以方便地查看和管理Consul集群的状态,包括服务列表、健康检查、键值对等。
- cloud-payment-service-8001:http://localhost:8001/pay/get/info
- cloud-payment-service-8002:http://localhost:8002/pay/get/info

消费者-订单80模块修改POM并注册进consul,新增LoadBalancer组件

<!--loadbalancer-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
订单80模块修改Controler并启动80
cloud-payment-service 要与consul上注册名称一致。
@RestController
public class OrderController
{//public static final String PaymentSrv_URL = "http://localhost:8001";//先写死,硬编码public static final String PaymentSrv_URL = "http://cloud-payment-service";//服务注册中心上的微服务名称@Autowiredprivate RestTemplate restTemplate;/*** 一般情况下,通过浏览器的地址栏输入url,发送的只能是get请求* 我们模拟消费者发送get请求,but底层调用post方法,客户端消费者参数PayDTO可以不添加@RequestBody* @param payDTO* @return*/@GetMapping("/consumer/pay/add")public ResultData addOrder(PayDTO payDTO){return restTemplate.postForObject(PaymentSrv_URL + "/pay/add",payDTO,ResultData.class);}@GetMapping("/consumer/pay/get/{id}")public ResultData getPayInfo(@PathVariable Integer id){return restTemplate.getForObject(PaymentSrv_URL + "/pay/get/"+id, ResultData.class, id);}@GetMapping(value = "/consumer/pay/get/info")private String getInfoByConsul(){return restTemplate.getForObject(PaymentSrv_URL + "/pay/get/info", String.class);}
}
目前consul上的服务 将order也进行注册

测试


3.负载均衡演示案例-小总结
编码使用DiscoveryClient动态获取所有上线的服务列表

代码解释,修改80微服务的Controller
@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();
}
DiscoveryClient获取所有上线的服务列表数据:
cloud-consumer-order
cloud-payment-service
consul
cloud-payment-service WIN-C38UV4TIS4J 8001 http://WIN-C38UV4TIS4J:8001
cloud-payment-service WIN-C38UV4TIS4J 8002 http://WIN-C38UV4TIS4J:8002
结合前面实操,负载选择原理小总结
负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标 ,每次服务重启动后rest接口计数从1开始。List instances = discoveryClient.getInstances("cloud-payment-service");如: List [0] instances = 127.0.0.1:8002List [1] instances = 127.0.0.1:80018001+ 8002 组合成为集群,它们共计2台机器,集群总数为2, 按照轮询算法原理:当总请求数为1时: 1 % 2 =1 对应下标位置为1 ,则获得服务地址为127.0.0.1:8001当总请求数位2时: 2 % 2 =0 对应下标位置为0 ,则获得服务地址为127.0.0.1:8002当总请求数位3时: 3 % 2 =1 对应下标位置为1 ,则获得服务地址为127.0.0.1:8001当总请求数位4时: 4 % 2 =0 对应下标位置为0 ,则获得服务地址为127.0.0.1:8002如此类推......
4.负载均衡算法原理
官网算法
默认算法
默认两种算法轮询和随机

public class RoundRobinLoadBalancer implementsReactorServiceInstanceLoadBalancer
public class RandomLoadBalancer implementsReactorServiceInstanceLoadBalancer
主要用于配置和定制特定的客户端负载均衡器行为。@LoadBalancerClient 可以用来为特定的微服务配置负载均衡器的相关设置。通过指定name或value属性(两者通常可以互换使用),你可以指定一个服务的ID,该ID与Spring Cloud consul(或其他服务注册中心)中注册的服务名相对应。这样,你就 可以为特定的服务定制负载均衡策略、重试机制等。在微服务架构中,不同的服务可能需要不同的负载均衡配置。@LoadBalancerClient 允许你通过为不同的服务定义不同的配置类来实现 配置的隔离。这样, 每个服务都可以根据自身的需求来定制负载均衡行为,而不会影响到其他服务。还允许你通过configuration属性来指定一个配置类,该配置类中可以定义 自定义的负载均衡器、规则、拦截器等。
算法切换
从默认的轮询,切换为 随机算法,修改RestTemplateConfig
/*** LoadBalancer默认轮询算法切换随机算法* @LoadBalancerClient @Bean*/
@Configuration
@LoadBalancerClient(//下面的value值大小写一定要和consul里面的名字一样,必须一样value = "cloud-payment-service",configuration = RestTemplateConfig.class)
public class RestTemplateConfig
{@Bean@LoadBalanced //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力public RestTemplate restTemplate(){return new RestTemplate();}@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}
}
@LoadBalancerClient(name = "my-service", configuration = MyServiceLoadBalancerConfig.class)
public class MyServiceConfiguration { // 这里可以包含一些针对my-service的特定配置
} @Configuration
public class MyServiceLoadBalancerConfig { @Bean public IRule myCustomRule() { // 返回一个自定义的负载均衡规则 return new MyCustomRule(); }
}
测试
测试地址: http://localhost/consumer/pay/get/info实现效果:随机访问cloud-payment-service服务