Ribbon核心特性和工程组成
核心功能:
- Multiple and pluggable load balancing rules:多种可插拔的负载均衡规则
- Integration with service discovery:集成服务发现
- Built-in failure resiliency:内置弹性故障
- Cloud enabled:云上可用
- Clients integrated with load balancers:集成负载均衡的客户端
- Archaius configuration driven client factory:基于Archaius的客户端工厂
子工程构成:
- ribbon-core: includes load balancer and client interface definitions, common load balancer implementations, integration of client with load balancers and client factory.
- ribbon-eureka: includes load balancer implementations based on Eureka client, which is the library for service registration and discovery.
- ribbon-httpclient: includes the JSR-311 based implementation of REST client integrated with load balancers.
- ribbon-core:
- 负载均衡器的接口定义与默认实现
- 客户端的接口定义与默认实现
- 集成负载均衡器的客户端
- 客户端工厂
- ribbon-eureka:
- 基于Eureka客户端实现的负载均衡器
- ribbon-httpclient:
- 基于JSR-311实现且集成了负载均衡器的REST客户端
子项目定位理解:
- ribbon-core:提供核心组件
- ribbon-eureka:对接eureka
ribbon-httpclient:由于Netflix套件中使用JSR-311较多,所以提供JSR-311客户端是可以理解的。
比如eureka就使用了jersey提供服务,而jersey就是基于JAX-RS(JSR-311 & JSR-339)规范做的服务端框架负载均衡
默认的负载均衡:
轮询算法
- 响应时间加权算法
-
集成服务发现
实现一个返回服务列表的接口,即可集成服务发现。如果服务发现使用的是Eureka,那连接口都不需要实现,使用Eureka子项目就行
可上云(Cloud enabled)
专门为云环境设计和测试。支持云环境中的一些概念。
比如,ribbon有考虑可用区的概念,在负载均衡时,会尽可能将请求负载到同一可用区。分发请求时也会尽可能避免把请求都分发到服务质量差的可用区。
再比如,ribbon能预热连接,优化云上遇到的冷启动问题内置弹性故障
ribbon可以通过IPing接口周期性地检查服务的活跃性,并且自动过滤不活跃的服务。
集成负载均衡的客户端
ribbon提供了客户端接口和集成负载均衡的客户端抽象类。通过接口和抽象类,可以很方便地开发自己的客户端。并且httpclient子项目也有提供客户端实现。
基于Archaius的客户端工厂
ribbon提供了基于Archaius的客户端工厂,这样使用者就可以很容易地将客户端配置化。
Ribbon配置
ribbon一般使用properties文件进行配置,格式如下:
<clientName>.<nameSpace>.<propertyName>=<value>
clientName:从客户端工厂中创建客户端时用到的名字
- nameSpace:属性的命名空间。一般为是ribbon(默认命名空间)
- propertyName:属性名。公共属性字段可以参考
CommonClientConfigKey
类示例代码
public static void main(String[] args) throws Exception {
ConfigurationManager.loadPropertiesFromResources("sample-client.properties"); // 1
System.out.println(ConfigurationManager.getConfigInstance().getProperty("sample-client.ribbon.listOfServers"));
RestClient client = (RestClient) ClientFactory.getNamedClient("sample-client"); // 2
HttpClientRequest request = HttpClientRequest.newBuilder().setUri(new URI("/")).build(); // 3
for (int i = 0; i < 20; i++) {
HttpClientResponse response = client.executeWithLoadBalancer(request); // 4
System.out.println("Status code for " + response.getRequestedURI() + " :" + response.getStatus());
}
ZoneAwareLoadBalancer lb = (ZoneAwareLoadBalancer) client.getLoadBalancer();
System.out.println(lb.getLoadBalancerStats());
ConfigurationManager.getConfigInstance().setProperty(
"sample-client.ribbon.listOfServers", "www.linkedin.com:80,www.google.com:80"); // 5
System.out.println("changing servers ...");
Thread.sleep(3000); // 6
for (int i = 0; i < 20; i++) {
HttpClientResponse response = client.executeWithLoadBalancer(request);
System.out.println("Status code for " + response.getRequestedURI() + " : " + response.getStatus());
response.releaseResources();
}
System.out.println(lb.getLoadBalancerStats()); // 7
}
- 使用Archaius加载配置文件
- 使用客户端工厂获取客户端对象
- 使用构建器构建请求
- 调用有负载均衡功能的请求API
- 动态更改服务列表配置
- 等待服务列表刷新
- 打印负载均衡统计信息
Ribbon负载均衡
功能概览
核心功能:
- 向通信客户端提供各个服务的域名或者IP
- 遵循某种规则轮换服务的域名或IP
高级功能:
- 可以将服务器划分出不同可用区,根据客户端的可用区,建立客户端和服务器的亲和关系,降低网络访问开销
- 对服务器进行统计,剔除服务质量低下的服务器(高延迟或者频繁故障的服务器)
- 保存可用区的统计信息,剔除在不可用区域中的服务器
PS:想使用高级功能需要使用Ribbon自己提供的客户端。或者自己实现客户端,集成负载均衡器的同时向负载均衡器提供统计数据。
功能组件
- Rule:决定最终返回服务器列表中的哪个服务器
- Ping:后台运行的组件,检查服务器是否存活
- ServerList:分为静态列表和动态列表。动态列表会在后台周期性刷新列表
功能组件可以通过代码配置,也可以通过配置文件进行配置。属性列表如下:
<clientName>.<nameSpace>.NFLoadBalancerClassName
<clientName>.<nameSpace>.NFLoadBalancerRuleClassName
<clientName>.<nameSpace>.NFLoadBalancerPingClassName
<clientName>.<nameSpace>.NIWSServerListClassName
<clientName>.<nameSpace>.NIWSServerListFilterClassName
公共Rule组件
RoundRobinRule
AvailabilityFilteringRule
会过滤掉服务器列表中“短路”状态的服务器和并发过高的服务器。
如果RestClient最后三次请求都没有与实例(服务器)成功建立连接,就会触发“短路”,不再返回该实例。
第一次触发短路,短路状态会持续30秒,然后短路状态恢复。
但是,如果连续触发短路,短路时间会指数级增加。(30s * 2)
配置文件:
# 进入短路状态要连续故障的次数, 默认为3
niws.loadbalancer.<clientName>.connectionFailureCountThreshold
# 短路恢复所需时间的上限,即使恢复时间指数增加也不能超过这个上限,默认30(30秒)
niws.loadbalancer.<clientName>.circuitTripMaxTimeoutSeconds
# 服务器高并发判定的连接数阈值, 默认为Integer.MAX_INT
<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit
WeightedResponseTimeRule
权重规则。规则会根据服务器的响应时间算出一个“权重”,响应时间越长,权重就越小。规则还是会随机选择服务器,但是每个服务器被选中的概率和权重成比例。
可以通过API开启权重规则,也可以通过下方的配置开启权重规则:
<clientName>.<clientConfigNameSpace>.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.WeightedResponseTimeRule
公共ServerList组件
Adhoc static server list
可以通过 BaseLoadBalancer.setServersList()
设置一个静态的ServerList
ConfigurationBasedServerList
默认使用的ServerList。从配置文件中获取服务器列表,可以监视配置文件变更
使用方式:将服务器列表加到配置文件中
sample-client.ribbon.listOfServers=www.microsoft.com:80,www.yahoo.com:80,www.google.com:80
DiscoveryEnabledNIWSServerList
使用Eureka客户端获取服务器列表,配置文件如下:
myClient.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
# 服务在Eureka上注册的服务名必须和VipAddress保持一致
myClient.ribbon.DeploymentContextBasedVipAddresses=myservice
公共的ServerListFilter组件
ServerListFilter是DynamicServerListLoadBalancer(动态服务器列表)用于过滤从ServerList实现返回的服务器的组件。在Ribbon中有两个ServerListFilter的实现。
ZoneAffinityServerListFilter
只要客户端区中还有可用的服务器,就会过滤掉与客户端不在同一区域的服务器。
开启方法:
myclient.ribbon.EnableZoneAffinity=true
ServerListSubsetFilter
过滤器确保客户端只能看到ServerList的一个(固定数量的)子集。它还会周期性地使用新的服务器替换子集中可用性差的服务器。
使用方法:
myClient.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
# 服务在Eureka上注册的服务名必须和VipAddress保持一致
myClient.ribbon.DeploymentContextBasedVipAddresses=myservice
myClient.ribbon.NIWSServerListFilterClassName=com.netflix.loadbalancer.ServerListSubsetFilter
# 子集中服务器的数量。默认为20
myClient.ribbon.ServerListSubsetFilter.size=5