5.LoadBalancer负载均衡服务调用

目录

一、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目前也进入维护模式

Ribbon简介

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套
客户端
负载均衡的工具。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是
提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

官网Ribbon维护模式信息

项目状态:维护中…

spring官网推荐Rabbon平替组件loadbalancer

二、spring-cloud-loadbalancer概述

官网
Spring Cloud Commons

官网学习地址
Cloud Native Applications

github地址
GitHub – spring-guides/gs-spring-cloud-loadbalancer: Client-Side Load-Balancing with Spring Cloud LoadBalancer :: Dynamically select correct instance for the request :: spring-cloud,spring-cloud-loadbalancer,spring-cloud-commons

loadbalancer目前在springcloudcommons下

LB负载均衡(Load Balance)是什么

简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用),常见的负载均衡有软件Nginx,LVS,硬件 F5等

spring-cloud-starter-loadbalancer组件是什么

Spring Cloud LoadBalancer是由SpringCloud官方提供的一个开源的、简单易用的
客户端负载均衡器,它包含在SpringCloud-commons中用它来替换了以前的Ribbon组件。相比较于Ribbon,SpringCloud LoadBalancer不仅能够支持RestTemplate,还支持WebClient(WeClient是Spring Web Flux中提供的功能,可以实现响应式异步请求)

loadbalancer本地负载均衡客户端 VS Nginx服务端负载均衡区别 

Nginx是
服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求,即负载均衡是由服务端实现的。 

loadbalancer
本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。

三、spring-cloud-loadbalancer负载均衡解析

1.负载均衡演示案例-理论

架构说明:80通过轮询负载访问8001/8002/8003

LoadBalancer 在工作时分成两步:

第一步,先选择ConsulServer从服务端查询并拉取服务列表,知道了它有多个服务(上图3个服务),这3个实现是完全一样的,

默认轮询调用谁都可以正常执行。类似生活中求医挂号,某个科室今日出诊的全部医生,客户端你自己选一个。

第二步,按照指定的负载均衡策略从server取到的服务注册列表中由客户端自己选择一个地址,所以LoadBalancer是一个
客户端的
负载均衡器。

2.负载均衡演示案例-实操

官网参考地址:
Cloud Native Applications

按照8001拷贝后新建8002微服务
启动Consul,将8001/8002启动后注册进微服务

看到两个service已注册成功,
但是consul的key/value之前配置未进行持久化保存,已经不存在

Consul数据持久化配置并且注册为Windows服务
方式一:编写脚本的方式

1.D:devSoftlconsul 1.17.0 windows 386日录下

新建mydata文件夹
新建文件consul start.bat后缀为.bat

2.consul start.bat内容信息

@echo.服务启动......  
@echo off  
@sc create Consul binpath= "D:devSoftconsul_1.17.0_windows_386consul.exe agent -server -ui -bind=127.0.0.1 -client=0.0.0.0 -bootstrap-expect  1  -data-dir D:devSoftconsul_1.17.0_windows_386mydata   "
@net start Consul
@sc config Consul start= AUTO  
@echo.Consul start is OK......success
@pause

3.右键管理员权限打开

4.启动结果

5. win后台

6.后续consul的配置数据会保存进mydata文件夹,关机重启数据也是存在的

或者也可以启动的时候设置consul持久化目录

方式二:通过-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集群的状态,包括服务列表、健康检查、键值对等。

后台自启动Consul测试地址:
http://localhost:8500

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";//服务注册中心上的微服务名称

    @Autowired
    private 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也进行注册

测试

测试地址:
http://localhost/consumer/pay/get/info

通过该地址交替访问到8001、8002端口

3.负载均衡演示案例-小总结 

编码使用DiscoveryClient动态获取所有上线的服务列表

官网地址:
Service Discovery with Consul :: Spring Cloud Consul

代码解释,修改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()+"	"+element.getHost()+"	"+element.getPort()+"	"+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:8002

    List [1] instances = 127.0.0.1:8001

8001+ 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.负载均衡算法原理

官网算法

官网负载均衡算法地址:
Cloud Native Applications

默认算法

默认两种算法轮询和随机

轮询源码实现类

public class RoundRobinLoadBalancer implementsReactorServiceInstanceLoadBalancer

随机源码实现类

public class RandomLoadBalancer implements

ReactorServiceInstanceLoadBalancer

@LoadBalancerClient
解释

自定义客户端每个服务的负载均衡配置,且服务期间相互隔离。

主要用于配置和定制特定的客户端负载均衡器行为。

@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();
    }

    @Bean
    ReactorLoadBalancer<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服务

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容