一)Ribbon的介绍
1 什么是 Ribbon
1.Ribbon
是一个基于 Http 和 TCP 的客服端负载均衡工具,它是基于 Netflix Ribbon 实 现的。
2.它不像 spring cloud 服务注册中心、配置中心、API 网关那样独立部署,但是它几乎 存在于每个 spring cloud 微服务中。包括 feign 提供的声明式服务调用也是基于该 Ribbon 实现的。
3.ribbon 默认提供很多种负载均衡算法,例如 轮询、随机 等等。甚至包含自定义的负 载均衡算法。
2 Ribbon 解决了什么问题
他解决并提供了微服务的负载均衡的问题。
二)集中式与进程内负载均衡的区别
1 负载均衡解决方案的分类 目前业界主流的负载均衡方案可分成两类:
第一类:集中式负载均衡, 即在 consumer 和 provider 之间使用独立的负载均衡设施(可 以是硬件,如 F5, 也可以是软件,如 nginx), 由该设施负责把 访问请求 通过某种策略转发 至 provider;
负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间按照专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些用于负载均衡功能或模块等软件来完成请求分发工作,比如Nginx等。不论采用硬件负载均衡还是软件负载均衡,只要是服务端都能以类似下图的架构方式构建起来:
也就是说无论使用软件还是硬件负载均衡的设备都是要独立部署的。
第二类:进程内负载均衡,将负载均衡逻辑集成到 consumer,consumer 从服务注册中 心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的 provider。
Ribbon 就属于后者,它只是一个类库,集成于 consumer 进程,consumer 通过它来获取 到 provider 的地址。进程内负载均衡就是将复杂均衡算法写在程序内,由程序判断在进行服务访问的时候设定指定服务的负载均衡算法。
2 两种负载均衡方式结构图
主要看下的Rbbion结构图,在图中Customer内置负载均衡算法,在发送服务请求的时候将根据Customer写的负载均衡算法进行访问的集群Provider中的那个的服务。
三)Ribbon入门案例
测试默认的Ribbon负载均衡算法
在本机测试使用多环境配置的方式进行测试
启动成功注册中心出现集群的服务
端口为:9090、8080
启动Customer进行测试
1.完成Customer的注册
2.业务代码
/**
* @project_name:springcloud
* @date:2019/8/30:15:15
* @author:shinelon
* @Describe:
*/
@Service
public class UserService
{
/**
* 远程调用服务的代码的编写
* @return
*/
/**
* LoadBalancerClient:此对象相当于负载均衡器ribbon 负
* 载均衡器 ,通过此对象获取远程服务
*/
@Autowired
private LoadBalancerClient loadBalancerClient;
public Users getUsers()
{
//在微服务中使用的使用应用的名称获取服务的所以这里要给远程服务的应用名称
//ServiceInstance对象封装了远程服务的地址和端口等信息
ServiceInstance choose = this.loadBalancerClient.choose("eureka-provider");
//拼接URL
StringBuffer buffer = new StringBuffer();
buffer.append("http://").append(choose.getHost()).append(":").append(choose.getPort()).append("/user");
//打印调用的集群服务
System.out.println("Ribbon默认的负载均衡算法"+buffer.toString());
//使用MVC模板进行远程访问
RestTemplate restTemplate = new RestTemplate();
//ParameterizedTypeReference用于接收远程返回的对象
ParameterizedTypeReference<Users> type = new ParameterizedTypeReference<Users>()
{
};
//接收返回的对象
ResponseEntity<Users> responseEntity =restTemplate.exchange(buffer.toString(),HttpMethod.GET, null, type);
return responseEntity.getBody();
}
}
控制台结果,Ribbon默认采用的是轮询策略进行负载均衡
四)Ribbon常见的负载均衡策略
1 轮询策略(默认)
RoundRobinRule
轮询策略表示每次都顺序取 下一个 provider,比如一共有 5 个 provider,第 1 次取第 1 个,第 2 次取第 2 个,第 3 次取第 3 个,以 此类推
2 权重轮询策略 WeightedResponseTimeR ule
1.根据每个 provider 的响应 时间分配一个权重,响应时间越 长,权重越小,被选中的可能性越 低。
2.原理:一开始为轮询策略,并开 启一个计时器,每 30 秒收集一次 每个 provider 的平均响应时间, 当信息足够时,给每个 provider 附上一个权重,并按权重随机选择 provider,高权越重的 provider 会被高概率选中。这策略是比较方便的了,不需要我们考虑权重,或根据服务的响应时间动态的分配权重
3 随机策略 RandomRule 从 provider
列表中随机选择一个 provider
4 最少并发数策略
BestAvailableRule
选择正在请求中的并发数最 小的 provider,除非这个 provider 在熔断中。
5 在“选定的负载均 衡策略”基础上进行重 试机制 RetryRule
1.“选定的负载均衡策略”这 个策略是轮询策略 RoundRobinRule
2.该重试策略先设定一个阈值时 间段,如果在这个阈值时间段内当 选择 provider 不成功,则一直尝 试采用“选定的负载均衡策略:轮 询策略”最后选择一个可用的 provider
这样说可能有点不好理解,其实很简单轮询策略如果轮到了当前的节点,但是当前节点出现了异常,轮询策略不会在去尝试其他服务,而RetryRule则会在次尝试服务集群中的其他服务。
6 可用性敏感策略 AvailabilityFilteringRule:
过滤性能差的 provider,有 2 种:
第一种:过滤掉在 eureka 中处于 一直连接失败 provider
第二种:过滤掉高并发的 provider
7 区域敏感性策略 ZoneAvoidanceRule:
1.以一个区域为单位考察可 用性,对于不可用的区域整个丢 弃,从剩下区域中选可用的 provider
2.如果这个 ip 区域内有一个或多 个实例不可达或响应变慢,都会降 低该 ip 区域内其他 ip 被选中的权 重
3.此策略是站在更大的范围进行服务的访问,适合用于分布在不同地位置的服务。
五)修改负载均衡策略的方式
注意:Ribbion是在Customer中定义访问指定的服务的负载均衡策略
1.在代码修改
在启动类中添加指定的策略类即可
@SpringBootApplication
@EnableEurekaClient //消费者同样要注册到注册中心中
public class Application
{
/**
* 添加负载均衡策略
* @return
*/
@Bean
public RandomRule randomRule(){
return new RandomRule();
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
轮询策略已经改变
2.在配置文件内修改轮询的策略
注意在配置文件内修改的语法格式是:
指定的服务的名称+ribbion+NFLoadBalancerRuleClassName+指定的负载均衡规则
如下:
eureka-provider:#指定的服务名称,会根据指定的服务的进行指定的负载均衡算法
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule