• Ribbon本地实现负载均衡


    负载均衡Ribbon

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

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

    Ribbon本地负载均衡客户端和Nginx服务端负载均衡的区别

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

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

    负载均衡的算法

    ​ 负载均衡算法:rest接口第几次请求数%服务器集群总数量 = 实际调用服务器下表,每次服务器重启rest接口计数从1开始

    ​ 例:

    ​ 如果这里有y台机器

    ​ x为访问的次数

    ​ 负载均衡算法就是 x % y => 访问的下标(注:如果重启服务器将从第一次开始)

    使用entity返回

    @GetMapping("/getForEntity/{id}")
    public CommonResult<Payment> queryById2(@PathVariable Long id){
        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "payment/get/"+id,CommonResult.class);
        //表示返回编码是2开头的
        if(entity.getStatusCode().is2xxSuccessful()){
            return entity.getBody();
        }else{
            return new CommonResult<>(404,"操作失败");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Ribbon负载均衡策略

    • 随机:RandomRule
    • 轮询:RoundRobinRule
    • 最小并发:BestAvailabelRule
    • 过滤:AvailabilityFilteringRule
    • 响应时间:WeightedResponseTimeRule
    • 轮询重试:RetryRule
    • 性能可用性:ZoneAvoidanceRule

    自定义负载均衡算法

    1.定义负载均衡接口

    package com.yuan.lb;
    
    import org.springframework.cloud.client.ServiceInstance;
    
    import java.util.List;
    
    public interface LoadBalancer {
        //1.收集Eureka集群所有存活的服务器
        //ServiceInstance 服务实例
        ServiceInstance instances(List<ServiceInstance> serviceInstances);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.实现自己的负载均衡接口

    package com.yuan.lb.imp;
    
    import com.yuan.lb.LoadBalancer;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;
    
    @Component //让容器扫描到自己写的组件
    public class MyLB implements LoadBalancer {
    
        private AtomicInteger atomicInteger = new AtomicInteger(0);
    
        //得到数量在进行增加
        public final int getAndIncrement(){
            int current;
            int next;
            do{
                //第一次是0 因为上面设设置数值时赋值为0
                current = this.atomicInteger.get();
                //整型最大数 ——> 2147483647
                //第一次是0 0不大于2147483647 所以 next = 0 +1 注:current上面得到的是0 后面以此类推
                next = current >= 2147483647 ? 0 :current +1;
                //如果取到值就返回true 但是这里我们取反所以返回false跳出循环
            }while (!this.atomicInteger.compareAndSet(current,next));
            System.out.println("第几次访问next ========》 " + next);
            return next;
        }
    
        @Override
        //负载均衡算法:rest 接口第几次请求%服务器集群总数量 = 实际调用服务器位置小标,每次重启后rest接口计数从1开始
        public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
            //获取下标值
            int index = getAndIncrement() % serviceInstances.size();
    
            return serviceInstances.get(index);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    3.使用注解找到我们的load Balancer

    @Resource
    private LoadBalancer loadBalancer;
    
    • 1
    • 2

    4.使用我们的load Balancer来获取URI

    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    if (instances == null || instances.size()<=0){
        return null;
    }
    ServiceInstance serviceInstance = loadBalancer.instances(instances);
    //获取uri
    URI uri = serviceInstance.getUri();
    //拼接uri
    return restTemplate.getForObject(uri+"/payment/lb",String.class);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我是本期小编⚪⚪
    遇到Bug需要帮助,
    欢迎加wx:
    xmzl1988
    备注"csdn博客“
    温馨提示此为有偿服务;

  • 相关阅读:
    SpringBoot SpringBoot 基础篇 4 基于 SpringBoot 的SSMP 整合案例 4.11 表现层数据一致性处理【R对象】
    如何使用PS做出大小水泡组合文字效果呢
    Codeforces Round 753 (Div. 3)(集训队加训2)
    牛掰的dd命令,cpi0配合find备份(不会主动备份),od查看
    Git本地项目提交到Gitee的操作流程
    (十三) minAreaRect函数
    OBS 安装与考试参数设置及屏幕无法完全捕获、录屏不完整的解决方法
    GoFrame+Vue+ElementUI框架快速入门教程
    Git 修改已提交的用户名和邮箱
    在Java中使用SFTP传输文件
  • 原文地址:https://blog.csdn.net/weixin_42575720/article/details/126101868