上期内容我们讲了Cloud中非常重要的一个知识点Eureka服务注册与发现服务以及Eureka集群,有兴趣的同学可以从公众号中看一下。

Ribbon负载均衡:

3:实例验证.

4:Ribbon核心组件IRule .

5:自定义算法.

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

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负均衡算法,将 Netflix 的中间层服务连接在一起.Ribbon客户端组件 提供一系列完善的配置项如连接Timeout,重试等,简单的说就是在配置文件中列出Load Balancer(俗称LB)后面所有的机器 ,Ribbon 会自动的帮我们基于制定好的规则(简单轮洵,随机连接等)去连接这些机器,我们也很容易使用Ribbon实现负载均衡算法.

我们有3台服务器,每天有100万的访问量,那么负载均衡器的作用就是按一定的规则把这100万次的访问量分配到3台服务器上.

1:集中式LB:

偏硬件,就是在服务的消费方与提供方之间使用独立的LB设施(可以是硬件,如 F5,也可以是软件,如 Nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方.

2:进程内LB

偏软件,将LB逻辑集成到消费方.消费方从服务注册中心获知有哪些地址可用.然后自己再从这些地址中选择出一个合适的服务器.Ribbon属于进行内LB,是一个类库,集成于消费方进程.消费方通过它来猎取到服务提供方的地址.

注意:Ribbon是使用在客户端的。

比如,我们二期搭建的项目中,有两个模块:

1 : 部门服务端:

msc-api-department-12001

2 : 部门客户端:

msc-consumer-department-80

客户端通过服务端提供的Rest接口进行方法调用.

所以我们需要在客户端进行配置.

打开部门客户端的pom.xml,加入Ribbon的Maven配置

1 <!--Ribbon 负载均衡 开始--> 2<dependency> 3    <groupId>org.springframework.cloud</groupId> 4    <artifactId>spring-cloud-starter-eureka</artifactId> 5</dependency> 6<dependency> 7    <groupId>org.springframework.cloud</groupId> 8    <artifactId>spring-cloud-starter-ribbon</artifactId> 9</dependency>10<dependency>11    <groupId>org.springframework.cloud</groupId>12    <artifactId>spring-cloud-starter-config</artifactId>13</dependency>14<!--Ribbon 负载均衡 结束-->application.yml

把客户端注册到Eureka服务中

在RestTemplate的获取方式中添加注解

@LoadBalanced

1/** 2 * 配置类 3 */ 4@Configuration 5public class ConfigBean { 6    /** 7     * 8     * @return 9     */10    @Bean11    @LoadBalanced //开启负载均衡12    public RestTemplate getRestTemplate(){13        return new RestTemplate();14    }15}添加Eureka客户端启动注解

@EnableEurekaClient

1@SpringBootApplication2@EnableEurekaClient3public class MscConsumerApplication {45    public static void main(String[] args) {6        SpringApplication.run(MscConsumerApplication.class,args);7    }8}修改Controller的Rest接口地址

之前是通过一个固定的地址,现修改为Eureka服务器上面的服务名称

1@RestController 2@RequestMapping(value = "/consumer") 3public class DepartConsumerController { 4 5    /** 6     * Rest 对象 7     */ 8    @Autowired 9    private RestTemplate restTemplate;10    /**11     * 服务器Rest地址12     */13//    private String serverAddress = "http://localhost:12001/department/";14    private String serverAddress = "http://MSC-DEPARTMENT/department/";好处:

Ribbon和Eureka整合后客户端可以直接调用服务而不用再关心地址和端口号。

Ribbon在工作时分成两步:

第一步先选择EurekaServer,它优先选择在同一个区域内负载较少的Server;

第二步再根据用户指定的策略,从Server取到的服务注册列表中选择一个地址.

第一步:创建三份相同的部门Server,如下图

第二步:创建三份相同的数据库(脚本见二期)

第三步:修改各自的application.yml;

修改内容:

1 : 服务端口号;

2 : 数据库

3 : instance-id(实例ID)

启动服务我们发现服务地址变成了三个,如下图

RoundRobinRule:

RandomRule:

AvailabilityFilteringRule:

先过滤掉由于多次访问故障而处于断路器跳闸状态的服务.还有并发的连接数量超过阈值的服务.然后对剩余的服务列表按照轮洵策略进行访问.

WeightedResponseTimeRule:

根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够时切换WeightedResponseTimeRule.

先按照RoundRobinRule和策略获取服务,如果获取服务失败则在指定时间内进行重试,获取可用服务.

BestAvailableRule:

先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务.

ZoneAvoidanceRule:

默认规则,复合判断Server所在区域的性能和Server的可用性选择服务器

在配置类中加声明一个Bean返回IRule。

1/** 2 * 配置类 3 */ 4@Configuration 5public class ConfigBean { 6    /** 7     * @return 8     */ 9    @Bean10    @LoadBalanced //开启负载均衡11    public RestTemplate getRestTemplate(){12        return new RestTemplate();13    }14    /**15     * 切换其他负载堪称算法16     * 1:RoundRobinRule17     * 2:RandomRule18     * 3:AvailabilityFilteringRule19     * 4:ZoneAvoidanceRule20     * 5:WeightedResponseTimeRule21     * 6:RetryRule22     * 7:BestAvailableRule23     * @return24     */25    @Bean26    public IRule xiaobaibiRule(){27        // 切换为随机算法28        return new RandomRule();29    }30}自定义算法工作中难免会遇到Ribbon自带算法不满足我们需求的时候。比如:

我们需要进行每个服务访问5次后才能进行下一个服务的轮洵;

1:重新创建一个高于SpringBoot主启动类的package

2:在第一步创建的包中重新创建一个Config类.

这里我们先使用自带的随机算法来验证程式写的是否正确.

1package com.xiaobaibi.rule; 2 3import com.netflix.loadbalancer.IRule; 4import com.netflix.loadbalancer.RandomRule; 5import org.springframework.context.annotation.Bean; 6import org.springframework.context.annotation.Configuration; 7 8@Configuration 9public class XiaoBaibiRibbonRule {1011    @Bean12    public IRule xiaobaibiRule(){1314        return new RandomRule();15    }16}3:在SpringBoot主启动类中加入注解:

指明自定义的算法适用于哪个Server,自定义算法的Class

1@SpringBootApplication2@EnableEurekaClient3@RibbonClient(name = "MSC-DEPARTMENT", configuration = XiaoBaibiRibbonRule.class)4public class MscConsumerApplication {56    public static void main(String[] args) {7        SpringApplication.run(MscConsumerApplication.class,args);8    }9}4:自己写一个算法类;

继承:AbstractLoadBalancerRule

1package com.xiaobaibi.rule; 2 3import com.netflix.client.config.IClientConfig; 4import com.netflix.loadbalancer.AbstractLoadBalancerRule; 5import com.netflix.loadbalancer.ILoadBalancer; 6import com.netflix.loadbalancer.Server; 7 8import java.util.List; 910/**11 * 自定义Ribbon算法类12 * 共三个服务,每个服务连续使用5次,5次后换下一个服务,以此规律进行轮回13 */14public class MyRule  extends AbstractLoadBalancerRule {15    /**16     * 每次服务最大连续使用次数17     */18    private int total = 4;19    /**20     * 当前使用服务器编号21     */22    private int currentIndex = 0;2324    /**25     * 服务器选择算法26     * @param lb27     * @param key28     * @return29     */30    @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})31    public Server choose(ILoadBalancer lb, Object key) {32        if (lb == null) {33            return null;34        } else {35            Server server = null;36            while(server == null) {37                if (Thread.interrupted()) {38                    return null;39                }40                List<Server> upList = lb.getReachableServers();41                List<Server> allList = lb.getAllServers();42                int serverCount = allList.size();43                if (serverCount == 0) {44                    return null;45                }46//              主要逻辑47                if (total > 0){48                    total --;49                }else{50                    total = 4;51                    ++ currentIndex;52                    if(currentIndex == upList.size()){53                        currentIndex = 0;54                    }55                }56                server = (Server)upList.get(currentIndex);57                if (server == null) {58                    Thread.yield();59                } else {60                    if (server.isAlive()) {61                        return server;62                    }63                    server = null;64                    Thread.yield();65                }66            }67            return server;68        }69    }70    public Server choose(Object key) {71        return this.choose(this.getLoadBalancer(), key);72    }73    public void initWithNiwsConfig(IClientConfig clientConfig) {}74}5 : 修改第二步中的Config类:

就是在我们第二步创建的类中,第二步我们使用了自带的随机算法,现在修改为我们自己的算法.

1/** 2 * 自定义 Ribbon 算法 3 */ 4@Configuration 5public class XiaoBaibiRibbonRule { 6 7    @Bean 8    public IRule xiaobaibiRule(){ 9//        return new RandomRule();10        return new MyRule();11    }12}6 : 启动服务访问客户端正常

负载均衡在我们的日常项目中随处可见,特别是出现特殊时候,比如双十一时,TAOBAO就需要通过增加服务器集群来保证服务的正常.

[ scdemo] : 本期Demo程式;

[ 2021] : SpringCloud视频地址.

[sbsw] :小编所用的JDK,Maven,IDEA.

[mysql] 或 [mysql.exe]获取mysql的安装包与安装教程.

原创不易,点个赞分享出去吧.感谢支持.