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

    示例代码

    1. public static void main(String[] args) throws Exception {
    2. ConfigurationManager.loadPropertiesFromResources("sample-client.properties"); // 1
    3. System.out.println(ConfigurationManager.getConfigInstance().getProperty("sample-client.ribbon.listOfServers"));
    4. RestClient client = (RestClient) ClientFactory.getNamedClient("sample-client"); // 2
    5. HttpClientRequest request = HttpClientRequest.newBuilder().setUri(new URI("/")).build(); // 3
    6. for (int i = 0; i < 20; i++) {
    7. HttpClientResponse response = client.executeWithLoadBalancer(request); // 4
    8. System.out.println("Status code for " + response.getRequestedURI() + " :" + response.getStatus());
    9. }
    10. ZoneAwareLoadBalancer lb = (ZoneAwareLoadBalancer) client.getLoadBalancer();
    11. System.out.println(lb.getLoadBalancerStats());
    12. ConfigurationManager.getConfigInstance().setProperty(
    13. "sample-client.ribbon.listOfServers", "www.linkedin.com:80,www.google.com:80"); // 5
    14. System.out.println("changing servers ...");
    15. Thread.sleep(3000); // 6
    16. for (int i = 0; i < 20; i++) {
    17. HttpClientResponse response = client.executeWithLoadBalancer(request);
    18. System.out.println("Status code for " + response.getRequestedURI() + " : " + response.getStatus());
    19. response.releaseResources();
    20. }
    21. System.out.println(lb.getLoadBalancerStats()); // 7
    22. }
  1. 使用Archaius加载配置文件
  2. 使用客户端工厂获取客户端对象
  3. 使用构建器构建请求
  4. 调用有负载均衡功能的请求API
  5. 动态更改服务列表配置
  6. 等待服务列表刷新
  7. 打印负载均衡统计信息

    Ribbon负载均衡

    功能概览

    核心功能:
  • 向通信客户端提供各个服务的域名或者IP
  • 遵循某种规则轮换服务的域名或IP

高级功能:

  • 可以将服务器划分出不同可用区,根据客户端的可用区,建立客户端和服务器的亲和关系,降低网络访问开销
  • 对服务器进行统计,剔除服务质量低下的服务器(高延迟或者频繁故障的服务器)
  • 保存可用区的统计信息,剔除在不可用区域中的服务器

PS:想使用高级功能需要使用Ribbon自己提供的客户端。或者自己实现客户端,集成负载均衡器的同时向负载均衡器提供统计数据。

功能组件

  • Rule:决定最终返回服务器列表中的哪个服务器
  • Ping:后台运行的组件,检查服务器是否存活
  • ServerList:分为静态列表和动态列表。动态列表会在后台周期性刷新列表

功能组件可以通过代码配置,也可以通过配置文件进行配置。属性列表如下:

  1. <clientName>.<nameSpace>.NFLoadBalancerClassName
  2. <clientName>.<nameSpace>.NFLoadBalancerRuleClassName
  3. <clientName>.<nameSpace>.NFLoadBalancerPingClassName
  4. <clientName>.<nameSpace>.NIWSServerListClassName
  5. <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