4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下)

这篇具有很好参考价值的文章主要介绍了4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 前言

1.1 Ribbon负载均衡架构图

  • 我们在上篇文章的基础上继续Ribbon的负载均衡,为了更清晰,再放一次架构图,如下:
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡
    关于图的更多解释,请看Ribbon负载均衡上篇。
  • 关于上篇请看下面文章,如下:
    3-Spring cloud之搭建Ribbon负载均衡——服务器上实操(上).

2. Ribbon自带的负载均衡

2.1 Ribbon自带的负载均衡算法

  • Ribbon负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类,如下:
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡

    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡

  • 简单说一下这些规则文章来源地址https://www.toymoban.com/news/detail-529490.html

    • RoundRobinRule:轮询策略。
    • WeightedResponseTimeRule
      • 根据平均响应时间计算服务的权重,响应时间越快服务权重越大杯选中的概率越高。刚启动时如果统计信息不足,则使用 RoundRobinRule(轮询策略),等统计信息足够,则会切换到 WeightedResponseTimeRule 策略。
    • RandomRule
      • 随机策略,即:随机选择一个可用的服务器。
    • RetryRule
      • 重试机制的选择策略
      • 先按 RoundRobinRule(轮询策略)的策略获取服务,如果获取服务失败,则在指定时间内进行重试,获取可用的服务。
    • BestAvailableRule
      • 先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。
    • AvailabilityFilteringRule
      • 先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务(并发连接的上限,可以由客户端的 ActiveConnectionsLimit 属性进行配置),然后对剩余的服务列表按照RoundRobinRule(轮询策略)的策略进行访问。
    • ZoneAvoidanceRule
      • 以区域可用的服务器为基础进行服务器的选择,使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后对zone内的多个服务做轮询策略。
      • ZoneAvoidanceRule是默认实现。基于分区下的服务器的可用性选出可用分区列表,再从可用分区列表中随机选择一个分区,采用轮询的策略选择该分区的一个服务器。
        • 详细的讲解可以参考下面的文章,很不错,如下:
          Ribbon架构篇 - ZoneAvoidanceRule.

2.2 自带负载均衡之间的切换

  • 上篇文章已经知道,Ribbon默认的策略是轮询策略,那么怎么切换成别的策略呢?只需在配置类里加几行代码即可,想用什么策略自己修改即可,如下:
        @Bean  //如果此处没有配置就是默认的轮询策略,如果有配置就取配置的策略
        public IRule getMyIRule(){
    //        return new RoundRobinRule();//轮询策略
    //        return new RandomRule();//随机策略
    //        return new RetryRule();//重试机制的选择策略
            return new WeightedResponseTimeRule();//权重策略
      //              ……
    
        }
    
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡

3. Ribbon自定义负载均衡

3.1 自定义Ribbon负载均衡(简单试用)

3.1.1 添加自定义轮询策略配置类

  • 注意:此配置类不能与主启动类同目录;
  • 这里只是为了简单演示此配置类生效问题,所以用的算法还是上面提到过的Ribbon负载的算法,如下:
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡
    package com.liu.susu.config.ribbon;
    
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    import com.netflix.loadbalancer.RoundRobinRule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @Description  自定义轮询策略
     * @Author susu
     */
    @Configuration
    public class MyRibbonRule { //注意:此配置类不能与主启动类同目录
    
        @Bean
        public IRule getMyIRule(){
    
            return new RandomRule();//随机策略
    //        return new RoundRobinRule();//轮询
    
        }
    
    }
    

3.1.2 启动类添加注解@RibbonClient

  • 如下:
    //此注解用来加载自定义的ribbon负载均衡配置类MyRibbonRule.java
    @RibbonClient(name = "DOG-PROVIDER", configuration = MyRibbonRule.class)
    
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡

3.1.3 重启启动服务消费者,看效果

  • 这里就不再演示了,就是访问多点几次看看效果有没能达到。

3.2 自定义Ribbon负载均衡(自定义算法)

3.2.1 首先查看Ribbon轮询策略的源码

  • 如下:
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡
    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package com.netflix.loadbalancer;
    
    import com.netflix.client.config.IClientConfig;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class RoundRobinRule extends AbstractLoadBalancerRule {
        private AtomicInteger nextServerCyclicCounter;
        private static final boolean AVAILABLE_ONLY_SERVERS = true;
        private static final boolean ALL_SERVERS = false;
        private static Logger log = LoggerFactory.getLogger(RoundRobinRule.class);
    
        public RoundRobinRule() {
            this.nextServerCyclicCounter = new AtomicInteger(0);
        }
    
        public RoundRobinRule(ILoadBalancer lb) {
            this();
            this.setLoadBalancer(lb);
        }
    
        public Server choose(ILoadBalancer lb, Object key) {
            if (lb == null) {
                log.warn("no load balancer");
                return null;
            } else {
                Server server = null;
                int count = 0;
    
                while(true) {
                    if (server == null && count++ < 10) {
                        List<Server> reachableServers = lb.getReachableServers();
                        List<Server> allServers = lb.getAllServers();
                        int upCount = reachableServers.size();
                        int serverCount = allServers.size();
                        if (upCount != 0 && serverCount != 0) {
                            int nextServerIndex = this.incrementAndGetModulo(serverCount);
                            server = (Server)allServers.get(nextServerIndex);
                            if (server == null) {
                                Thread.yield();
                            } else {
                                if (server.isAlive() && server.isReadyToServe()) {
                                    return server;
                                }
    
                                server = null;
                            }
                            continue;
                        }
    
                        log.warn("No up servers available from load balancer: " + lb);
                        return null;
                    }
    
                    if (count >= 10) {
                        log.warn("No available alive servers after 10 tries from load balancer: " + lb);
                    }
    
                    return server;
                }
            }
        }
    
        private int incrementAndGetModulo(int modulo) {
            int current;
            int next;
            do {
                current = this.nextServerCyclicCounter.get();
                next = (current + 1) % modulo;
            } while(!this.nextServerCyclicCounter.compareAndSet(current, next));
    
            return next;
        }
    
        public Server choose(Object key) {
            return this.choose(this.getLoadBalancer(), key);
        }
    
        public void initWithNiwsConfig(IClientConfig clientConfig) {
        }
    }
    
    

3.2.2 创建自己的轮询策略

3.2.2.1 新建自定义轮询策略类
  • 设计思路:
    将原来的轮询改成轮询的时候每台服务器执行两次。
  • 根据上面自带的轮询策略进行修改,主要修改代码,3处,如下:
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡
  • 修改后的完整代码如下:
    package com.liu.susu.config.ribbon;
    
    import com.netflix.client.config.IClientConfig;
    import com.netflix.loadbalancer.AbstractLoadBalancerRule;
    import com.netflix.loadbalancer.ILoadBalancer;
    import com.netflix.loadbalancer.Server;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @Description  自定义新的轮询策略(根据源码的轮询策略修改)
     * @Author susu
     */
    public class MyRoundRobinRule extends AbstractLoadBalancerRule {
        private AtomicInteger nextServerCyclicCounter;
        private static final boolean AVAILABLE_ONLY_SERVERS = true;
        private static final boolean ALL_SERVERS = false;
        private static Logger log = LoggerFactory.getLogger(MyRoundRobinRule.class);
    
        private int exeTimes =0; //每台服务器被访问执行调用的次数
    
        public MyRoundRobinRule() {
            this.nextServerCyclicCounter = new AtomicInteger(0);
        }
    
        public MyRoundRobinRule(ILoadBalancer lb) {
            this();
            this.setLoadBalancer(lb);
        }
    
        public Server choose(ILoadBalancer lb, Object key) {
            if (lb == null) {
                log.warn("no load balancer");
                return null;
            } else {
                Server server = null;
                int count = 0;
    
                exeTimes ++;
    
                while(true) {
                    if (server == null && count++ < 10) {
                        List<Server> reachableServers = lb.getReachableServers();
                        List<Server> allServers = lb.getAllServers();
    
                        int upCount = reachableServers.size();
                        int serverCount = allServers.size();
                        if (upCount != 0 && serverCount != 0) {
    
                            int nextServerIndex = this.nextServerCyclicCounter.get();
                            if (exeTimes >= 2){
                                nextServerIndex = this.incrementAndGetModulo(serverCount);
                                exeTimes = 0;
                            }
                            server = (Server)allServers.get(nextServerIndex);
    
                            if (server == null) {
                                Thread.yield();
                            } else {
                                if (server.isAlive() && server.isReadyToServe()) {
                                    return server;
                                }
    
                                server = null;
                            }
                            continue;
                        }
    
                        log.warn("No up servers available from load balancer: " + lb);
                        return null;
                    }
    
                    if (count >= 10) {
                        log.warn("No available alive servers after 10 tries from load balancer: " + lb);
                    }
    
                    return server;
                }
            }
        }
    
        private int incrementAndGetModulo(int modulo) {
            int current;
            int next;
            do {
                current = this.nextServerCyclicCounter.get();
                next = (current + 1) % modulo;
            } while(!this.nextServerCyclicCounter.compareAndSet(current, next));
    
            return next;
        }
    
        public Server choose(Object key) {
            return this.choose(this.getLoadBalancer(), key);
        }
    
        public void initWithNiwsConfig(IClientConfig clientConfig) {
        }
    
    
    
    }
    
    
3.2.2.2 启用自定义轮询策略类
  • 如下:
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡
  • 启动,测试看效果
    4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下),# 分布式架构,spring cloud等,spring cloud,ribbon,负载均衡
    好了,到这里吧,具体的新轮询效果还是自己点点测试吧,我这里是可行的。

到了这里,关于4-Spring cloud之搭建Ribbon负载均衡——服务器上实操(下)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Cloud Alibaba全家桶(三)——微服务负载均衡器Ribbon与LoadBalancer

    本文为 微服务负载均衡器Ribbon与LoadBalancer 相关知识,下边将对 什么是Ribbon (包括: 客户端的负载均衡 、 服务端的负载均衡 、 常见负载均衡算法 ), Nacos使用Ribbon , Ribbon内核原理 (包括: Ribbon原理 , Ribbon负载均衡策略 , 饥饿加载 ), Spring Cloud LoadBalancer (包括:

    2024年02月02日
    浏览(40)
  • Spring Cloud Ribbon:负载均衡

    1. 介绍 Spring Cloud Ribbon 1.1 什么是 Spring Cloud Ribbon Spring Cloud Ribbon是Netflix开源的负载均衡器,它为分布式服务提供了客户端负载均衡的功能。Ribbon可以根据一系列的负载均衡算法和配置策略,将客户端的请求动态分发到多个服务实例上,以实现高可用性和性能优化。 1.2 负载均

    2024年02月19日
    浏览(43)
  • 【Spring Cloud 四】Ribbon负载均衡

    【Spring Cloud一】微服务基本知识 【Spring Cloud 三】Eureka服务注册与服务发现 目前公司项目使用的注册中心主要是Spring Cloud Alibaba的Nacos做的注册中心和配置中心。并且Nacos使用了Ribbon作为默认的负载均衡器。但是相当于将Ribbon的负载均衡给透明化了,日常开发明面上是看不到

    2024年02月14日
    浏览(50)
  • Spring Cloud - Ribbon 负载均衡原理、负载策略、懒加载

    目录 ​编辑 一、Ribbon 负载均衡原理 1.1、前言 1.2、负载均衡的工作流程 二、负载均衡策略 2.1、策略原理 2.2、负载均衡自定义方式 三、Ribbon 加载方式 ps:案例是上一章所讲的 “根据订单id查询订单的同时,把订单所属的用户信息一起返回”  。 上一章我们讲到 order-servi

    2024年02月09日
    浏览(37)
  • Cloud微服务:Ribbon负载均衡

    个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ 服务消费者(order-service)根据服务名称发起请求,请求地址(url):http://userservice/user/1。 请求被 负载均衡拦

    2024年04月26日
    浏览(36)
  • 【Spring Cloud】Ribbon 中的几种负载均衡策略

    负载均衡通常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而我们今天的主角 Ribbon 就属于后者——客户端负载均衡器。 服务端负载均衡器的问题是,它提供了更强的流量控制权,但无法满足不同的消费者希望使用不同负载均衡策略的需求,而使

    2024年02月15日
    浏览(61)
  • Spring Cloud 实战 | 解密负载均衡Ribbon底层原理,包含实战源码

    专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https://blog.csdn.net/superdangbo/category_9271502.html tensorflow专栏:https://blog.csdn.net/superdangbo/category_869

    2024年02月08日
    浏览(53)
  • 【Spring Cloud】Ribbon 实现负载均衡的原理,策略以及饥饿加载

    在前文《深入理解 Eureka 注册中心的原理、服务的注册与发现》中,介绍了如何使用 Eureka 实现服务的注册与拉取,并且通过添加 @LoadBalanced 注解实现了负载均衡。这种自动化的背后隐藏着许多疑问: 服务是在何时进行拉取的? 负载均衡是如何实现的? 负载均衡的原理和策略

    2024年02月07日
    浏览(47)
  • Spring Cloud(Finchley版本)系列教程(二) 客户端负载均衡Ribbon

    Spring Cloud(Finchley版本)系列教程(二) 客户端负载均衡Ribbon 目前主流的负载均衡方案有两种,一种是集中式均衡负载,在消费者与服务提供者之间使用独立的代理方式进行负载,比如F5、Nginx等。另一种则是客户端自己做负载均衡,根据自己的请求做负载,Ribbon就属于客户端自己

    2024年02月09日
    浏览(55)
  • Ribbon负载均衡+Nacos服务搭建

    首先通过RibbonLoadBalanceerClient获取服务名,并传给DynamicServerListLoadBalancer——通过EureKa-server获取服务名对应服务列表(也就是被注册到EureKa中的服务,可能包括不同端口的),然后我们会根据IRule中的服务负载均衡-选择某个服务,然后修改url发送请求; Ribbon的负载均衡是一个叫

    2024年02月10日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包