负载均衡是分布式架构的重点,其机制对整个集群的性能和稳定起到决定作用。Ribbon是奈飞的一个负载均衡项目,可为集群中的客户端通信提供服务。Spring Cloud对Ribbon进行集成,与注册中心组件(例如Eureka)集合,则可以实现客户端的负载均衡。
一、特性
1、负载均衡器,提供插拔式的负载均衡规则
2、支持包括http、tcp以及udp等多种协议
3、集成了负载均衡功能的客户端
二、子模块
1、ribbon-core:包括负载均衡器接口定义、客户端接口定义以及内置的负载均衡实现等API
2、ribbon-eureka:为Eureka客户端提供负载均衡实现类
3、ribbon-httpclient:对Apache的HttpClient进行封装,该模块提供具备负载均衡功能的REST客户端。
三、负载均衡器组件
Ribbon负载均衡器用于与集群中各个服务器进行通信。
1、基础功能
a、维护服务器的IP,DNS名称等信息
b、使用指定逻辑在服务器列表中循环
2、三个组件
rule:逻辑组件,决定从服务器列表中返回哪个服务器实例
ping:使用定时器来确保服务器网络可以连接
ServerList:服务器列表,提供静态配置和动态指定等两种方式来进行维护
四、负载均衡机制
1、负载均衡器接口定义了服务器的操作,提供服务器选择的服务。
一般使用ILoadBalancer接口。
静态配置的话,通常使用BaseLoadBalancer这个均衡器,则把Server信息放入到列表中,并传给listOfServers。
使用BaseLoadBalancer的chooseServer(Object key)来选择服务器,没有特别指定的情况下,默认俺轮询规则请求BaseLoadBalancer默认支持一个Ping检查功能,在没有显式设置的情况下,默认串行检查,这种策略在服务器数目较少的情况下适用。
public static void main(String[] args) {
//新建负载均衡器
BaseLoadBalancer lb = new BaseLoadBalancer();
// 添加服务器
List<Server> servers = new ArrayList<Server>();
servers.add(new Server("127.0.0.1", 8080));
servers.add(new Server("127.0.0.1", 8081));
lb.addServers(servers);
// 进行10次服务器选择
for(int i = 0; i < 10; i++) {
Server s = lb.chooseServer(null);
System.out.println(s);
}
}
动态维护的话,则用到了DynamicServerListLoadBalancer这个类,它继承了BaseLoadBalancer,微服务场景下,实时调整服务列表是非常必要的。
ServerListUpdater,是动态服务列表的更新器。PollingServerListUpdater是默认的更新策略,适用定时任务的方式去更新服务列表。EurekanotificationServerListUpdater则需要Eureka的事件监听器触发更新服务列表操作。
ServerListFilter是DynamicServerListLoadBalancer对服务器检查的一种优化设置。在ServerList 更新时,把符合条件的子集筛选出来检查。针对大规模服务器群来说,性能提升明显。
2、自定义负载规则
ribbon提供自定义负载规则功能,我们可以通过实现IRule接口,在choose方法中完成我们的逻辑。完成规则的定义后,把该对象传给BaseLoadBalancer。
除了编码方式外,ribbon允许我们以配置的方式进行负载规则的定义。
3、内置负载规则
ribbon内置7中负载规则,一般情况下能满足用户需求,如果个性化要求较高,再选择自定义规则。这七种负载规则如下:
RoundRobinRule:Robbin默认规则,通过轮询的方式进行服务器选择。
AvailabilityFilteringRule:忽略高并发和短路服务器。
其中在默认情况下,这台服务器如果3次连接失败被设置为短路状态,该状态将持续30秒。如果再次连接失败,短路的持续时间就会成几何级地增加。
WeightedResponseTimeRule:Robbin会给每一个服务器设定一个权重值,服务器的响应时间越长,对应的权重就会越小。这个规则会随机选择服务器,这个权重值可能会影响到服务器的选择。
ZoneavoidanceRule: 该规则以区域、可用的服务器为基础进行服务器的选择。使用Zone 对服务器进行分类,这个Zone 可以理解为一个机房,一个机架等。
BestAvailableRule: 忽略那些短路的服务器, 并选择并发数较低的服务器。
RandomRule:随机选择 随机选择一个可用的服务器。
RetryRule:包含了重试的选择逻辑,如果RoundRobinRule选择的服务器无法连接,那么将益智尝试选择一个可用的服务器。
4、Ping机制
负载均衡器会周期地去ping服务器来判断服务器是否存活,这就是Ping机制,我们需要实现IPing接口来实现Ping机制。默认情况下不启动Ping机制,DummyPing是默认的实现类,其逻辑是默认所有的服务都可用。
而PingUrl这个实现类,主动的去ping,发送Url到服务器,然后获取服务的可用状态。
public static void main(String[] args) throws Exception {
BaseLoadBalancer lb = new BaseLoadBalancer();
List<Server> servers = new ArrayList<Server>();
// 8080端口可正常连接
servers.add(new Server("localhost", 8080));
// 8899端口服务器应用不存在
servers.add(new Server("localhost", 8899));
lb.addServers(servers);
// 设置IPing实现类为PingUrl
lb.setPing(new PingUrl());
// 设置Ping时间间隔为2秒
lb.setPingInterval(2);
//休眠7秒,等待所有的响应
Thread.sleep(7000);
for(Server s : lb.getAllServers()) {
System.out.println(s.getHostPort() + " 状态:" + s.isAlive());
}
}
除了上述两种实现类外,还有NIWSDiscoveryPing。它需要才哟个Eureka的服务发现,选取服务为UP状态的服务。
5、自定义Ping
和Rule一样,除了适用Robbin内置的IPing实现类外,还可以自定义Ping实现类。需要我们实现IPing接口的isAlive方法,并把实现类配置到负载均衡器上去。
五、Spring Cloud的Robbin应用
Robbin已经被Spring Cloud集成了,与注册中心组件搭配,即可Spring Cloud架构下实现客户端的负载均衡。
服务调用者、服务提供者A、服务提供者是三个Eureka客户端,Eureka服务器作为注册中心。
1、服务调用者实现
首先,可实现IRule和IPing两个接口来对负载均衡器进行定义。
public class MyConfig {
@Bean
public IRule getRule() {
return new MyRule();
}
@Bean
public IPing getPing() {
return new MyPing();
}
}
其次,@RibbonClient注解,配置RibbonClient,可定义名称和对应的配置类
@RibbonClient(name="cloud-provider", configuration=MyConfig.class)
public class CloudProviderConfig {
}
再次,在控制器中提供对外服务(加入@RestController) ,并通过@LoadBalanced注释修饰,让RestTemplate具备负载均衡的功能。
六、总结
Ribbon负载均衡能力,是通过对负载均衡器配置,特别是负载规则和Ping机制,从而适应企业级开发需求。Sping Cloud对Robbin进行了封装,让使用更为方便。
更多推荐
Spring Cloud:负载均衡组件Ribbon机制、子模块
发布评论