Ribbon负载均衡策略

在上一章中讲到了 springcloud官方提供的负载均衡器
Ribbon 是一种客户端负载均衡器,原理是通过注册中心拉去服务实例列表,通过ribbon 提供的负载均衡策略选中特定的实例,进行请求
Ribbon默认的负载均衡策略是 轮询, 那么 Ribbon 有哪些负载均衡策略呢

Ribbon 的负载均衡策略

策略类

名称

备注

RandomRule

随机

随机选择 Server

RandomRobinRule

轮询

按顺序循环选择server

RetryRule

重试

在一个配置的时间段内 当选择server 不成功,则一直尝试选择一个可用的 server

BestAvailableRule

最低并发策略

逐个考察server,如果server 断路器打开则忽略,再选择其中并发连接最低的server

AvailabilityFilteringRule

可用过滤策略

过滤掉一直连接失败并被标记为 circuit tripped 的server, 过滤掉那些高并发连接的server【active connections 超过配置的阈值】

ResponseTimeWeightRule

响应时间加权策略

根据server 的响应时间选择.响应时间越短,权重越高,也容易被选中

ZoneAvoidanceRule

区域权重策略

综合判断server 所在区域的性能和server的可用 轮询选择, 并且pan判定一个AWS Zone 的运行性能是否可用,剔除不可以Zone中的所有server

tips : nginx 的负载策略有 轮询,权重weight,ip_hash等

知道了Ribbon 的默认负载均衡策略,也知道了Ribbon 提供的其他负载均衡策略.那么我们怎么才能够应用呢

全局替换掉默认的负载均衡策略,我们需要一个

全局配置策略-配置类
@Configuration
public class MyConfiguration{
	@Bean
	public IRule ribbonRule(){
		return new RandomRule();
	}
}

就这样简答的配置, 加上之后所有通过Ribbon的请求都会按照配置的规则来进行,七种负载均衡策略想使用哪种,在这里创建出来就行,当然你也可以自定义自己的负载均衡策略,

那么问题来了,如果我不想所有的都按同一种负载均衡策略,咋办

基于注解的局部策略配置

如果我们希望对某一个源服务 设置特有的负载均衡策略,可以通过@RibbonClient
但是值得注意的是

在使用它之前,我们需要对全局配置的代码进行改造

@Configuration
@AvoidScan
public class MyConfiguration{
	@Autowired
	IclinetConfig config;
	public Irule ribbonRule(){
		return new RandomRule();
	}
}

这里的@AvoidScan 注解是一个空的声明,稍后说明

注入的IclientConfig是针对客户端的 配置管理器 , 使用@RibbonClient注解时尤其需要注意它的作用 , 最后我们再启动类上加上 @RibbonClient 注解来对源服务进行负载均衡


@RibbonClient(name="client-a",configuration=MyConfiguration.class)
@componentScan(excludeFilters={@ComponentScan.Filter(type=FilterType.ANNOTATION,value={AvoidScan.class})})

关于这个配置,简答说一下

@RibbonClient配置还是一样的套路,意思对于client-a 服务采用 MyCofiguration配置的策略进行负载均衡

@ComponentScan中的配置意思是让Spring 不去扫描被@AvoidScan 注解标记的配置类,因为我们的配置是对于单个源服务配置的,不能应用于全局,不排除就会报错

总的来说,很简单,就是全局配置的类用@AvoidScan标记一下,在启动主类通过@RibbonClient指定服务和配置,并通过@ComponentScan将其排除全局扫描


当然如果你不习惯使用注解来配置,你也可以使用

基于配置文件的策略配置

基本语法是<client name>.ribbon.*,使用这个可以省略掉任何代码的配置

举个例子 : 对服务client-a 使用随机策略

client-a:
  ribbon:
  	NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

配置也很简单,指定服务应用的负载均衡类,至于类是哪个,可以去前面的的表中看看↑↑↑

在http请求中,免不了极端环境的失败,那么调用的时限控制和重试就很重要了

Ribbon的超时和重试

基本套路如下

client-a:
	ribbon:
		ConnectionTimeout: 30000
		ReadTimeout: 30000
		MaxAutoRetries: 1 #对第一次请求的服务重试次数
		MaxAutoRetriesNextServer: 1 # 要重试的下一个服务的最大数量【不包括第一个服务】
		MaxAutoRetriesAllOperations: true
Ribbon的饥饿加载

Ribbon在进行客户端负载均衡时并不是在启动的时候就加载上下文,而是在实际请求的时候才去创建【lazy load

这个特征会让我们的第一次请求显得特别疲软乏力,就像有的车,起步太肉了,没劲,严重的时候会造成请求超时

如果出现此类情况可以配置饥饿加载,在启动的时候加载上下文

ribbon:
	eager-load:
		enabled: true
		clients: client-a,client-b,client-c

配置文件一目了然,就不赘述了

说了这么久的官方配置,说好的自定义负载均衡策略呢,官方的我就是不爱用咋办

使用配置文件自定义Ribbon客户端

Ribbon是可以自定义客户端的
原理就是通过配置文件来默认加载一些类这一点在程序设计中是一个思想,以往大家能举一反三】,从而更改ribbon客户端的行为方式,并且使用这种方式的优先级最高,优先级高过使用@RibbonClient注解的配置和源码加载的相关Bean

以下给出语法说明

配置项

备注

<clientName>.ribbon.NFLoadBalancerClassName

指定 ILoadBalancer的实现类

<clientName>.ribbon.NFloadBalancerRuleClassName

指定IRule的实现类

<clientName>.ribbon.NFLoadBalancerPingClassName

指定IPing的实现类

<clientName>.ribbon.NIWSServerListClassName

指定ServerList的实现类

<clientName>.ribbon.NIWSServerListFilterClassName

指定ServerListFilter的实现类

然后给出一个配置示范:

client:
	ribbon:
		NIWSServerListClassName: com.netflix.loadBalancer.ConfigurationBasedServerList
		NFLoadBalancerRuleClassName: com.netflixloadbalancer.WeightedResponseTimeRule
Ribbon 脱离Eureka 的使用

一般来说,ribbon都是结合注册中心来使用的,因为需要Ribbon从注册中心拉取实例列表,来选择实例进行负载均衡

但是有一种情况是不适合这样做的,比如一个供很多人使用的公共注册中心,比如社区服务Eureka http://eureka.springcloud.cn,这就很容易产生服务入侵,所以就不要从Eureka 中读取服务列表,而是应该在Ribbon客户端指定源服务地址,让Ribbon脱离Eureka来使用

首先,我们需要在ribbon禁用eureka功能

ribbon:
	eureka:
		enabled: false

然后设置源服务列表

client:
	ribbon:
		listOfServers: http://localhost:8080,http://localhost:8081,http://localhost:8082

配置简单,不再赘述

总结

很简单的一章
1 ribbon的负载均衡策略,全局配置,指定服务配置,配置文件配置,
2 ribbon 的饥饿加载解决 第一次请求超时的问题
3 ribbon 自定义客户端
4 ribbon 脱离Eureka的使用,防止服务入侵