1. 概述
Ribbon 实现客户端的负载均衡. Spring cloud Feign 已经默认集成 Ribbon. 这是我开始学习 ribbon 和 fegin 迷惑的地方, 为什么很多文章都先讲了 ribbon, 然后直接讲 feign, 但是没有提到 Fegin 和 ribbon 的关系.
本文的主要的内容如下
1.ribbon 功能说明
2.ribbon 的 6 个主要组件: IRule,IPing,ServerList ,ServerListFilter,ServerListUpdater,ILoadBalancer
3.ribbon 通过属性文件配置 ribbon
2. Ribbon 功能说明
Ribbon 实现客户端的负载均衡, 负载均衡器提供很多对 http 和 tcp 的行为控制. Spring cloud Feign 已经集成 Ribbon, 所以注解 @FeignClient 的类, 默认实现了 ribbon 的功能.
Ribbon 主要包括如下功能
1. 支持通过 DNS 和 IP 和服务端通信
2. 可以根据算法从多个服务中选取一个服务进行访问
3. 通过将客户端和服务器分成几个区域 (zone) 来建立客户端和服务器之间的关系. 客户端尽量访问和自己在相同区域 (zone) 的服务, 减少服务的延迟
4. 保留服务器的统计信息, ribbon 可以实现用于避免高延迟或频繁访问故障的服务器
5. 保留区域 (zone) 的统计数据, ribbon 可以实现避免可能访问失效的区域 (zone)
3. Ribbon 主要组件
Ribbon 主要包含如下组件:
1.IRule
2.IPing
3.ServerList
4.ServerListFilter
5.ServerListUpdater
6.IClientConfig
7.ILoadBalancer
3.1. IRule
功能: 根据特定算法中从服务列表中选取一个要访问的服务 常用 IRule 实现有以下几种:
RoundRobinRule
轮询规则, 默认规则. 同时也是更高级 rules 的回退策略
AvailabilityFilteringRule
这个负载均衡器规则, 会先过滤掉以下服务:
a. 由于多次访问故障而处于断路器跳闸状态
b. 并发的连接数量超过阈值
然后对剩余的服务列表按照 RoundRobinRule 策略进行访问
WeightedResponseTimeRule
根据平均响应时间计算所有服务的权重, 响应时间越快, 服务权重越重, 被选中的概率越高. 刚启动时, 如果统计信息不足, 则使用 RoundRobinRule 策略, 等统计信息足够, 会切换到 WeightedResponseTimeRule.
RetryRule
先按照 RoundRobinRule 的策略获取服务, 如果获取服务失败, 则在指定时间内会进行重试, 获取可用的服务
BestAvailableRule
此负载均衡器会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务, 然后选择一个并发量最小的服务
RandomRule
随机获取一个服务
3.2. IPing
功能: 在后台运行的一个组件, 用于检查服务列表是否都活
NIWSDiscoveryPing
不执行真正的 ping. 如果 Discovery Client 认为是在线, 则程序认为本次心跳成功, 服务活着
PingUrl
此组件会使用 HttpClient 调用服务的一个 URL, 如果调用成功, 则认为本次心跳成功, 表示此服务活着.
NoOpPing
永远返回 true, 即认为服务永远活着
DummyPing
默认实现, 默认返回 true, 即认为服务永远活着
3.3. ServerList
功能: 存储服务列表. 分为静态和动态. 如果是动态的, 后台有个线程会定时刷新和过滤服务列表
常用 ServerList 实现有以下几种:
ConfigurationBasedServerList
从配置文件中获取所有服务列表
配置例子:
sample-client.ribbon.listOfServers=www.microsoft.com:80,www.yahoo.com:80,www.google.com:80
DiscoveryEnabledNIWSServerList
从 Eureka Client 中获取服务列表. 此值必须通过属性中的 VipAddress 来标识服务器集群. DynamicServerListLoadBalancer 会调用此对象动态获取服务列表
DomainExtractingServerList
代理类, 根据 ServerList 的值实现具体的逻辑
3.4. ServerListFilter
该接口允许过滤配置或动态获取的具有所需特性的服务器列表. ServerListFilter 是 DynamicServerListLoadBalancer 用于过滤从 ServerList 实现返回的服务器的组件.
常用 ServerListFilter 实现有以下几种:
ZoneAffinityServerListFilter
过滤掉所有的不和客户端在相同 zone 的服务, 如果和客户端相同的 zone 不存在, 才不过滤不同 zone 有服务.
启用此配置使用以下配置
<clientName>
.ribbon.EnableZoneAffinity=true ZonePreferenceServerListFilter
ZoneAffinityServerListFilter 的子类. 和 ZoneAffinityServerListFilter 相似, 但是比较的 zone 是发布环境里面的 zone. 过滤掉所有和客户端环境里的配置的 zone 的不同的服务, 如果和客户端相同的 zone 不存在, 才不进行过滤.
ServerListSubsetFilter
ZoneAffinityServerListFilter 的子类. 此过滤器确保客户端仅看到由 ServerList 实现返回的整个服务器的固定子集. 它还可以定期用新服务器替代可用性差的子集中的服务器.
要启用此过滤器, 请指定以下属性:
<clientName>.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
# the server must register itself with Eureka server with VipAddress "myservice"
<clientName>.ribbon.DeploymentContextBasedVipAddresses=myservice
<clientName>.ribbon.NIWSServerListFilterClassName=com.netflix.loadbalancer.ServerListSubsetFilter
# only show client 5 servers. default is 20.
<clientName>.ribbon.ServerListSubsetFilter.size=5
3.5. ServerListUpdater
功能: 被 DynamicServerListLoadBalancer 用于动态的更新服务列表. 常用的实现类:
PollingServerListUpdater
默认的实现策略. 此对象会启动一个定时线程池, 定时执行更新策略
EurekaNotificationServerListUpdater
当收到缓存刷新的通知, 会更新服务列表.
3.6. IClientConfig
功能: 定义各种配置信息, 用来初始化 ribbon 客户端和负载均衡器
常用 IClientConfig 实现有以下几种:
DefaultClientConfigImpl
IClientConfig 的默认实现, 配置文件里的部分值为 ribbon.
3.7. ILoadBalancer
定义软件负载平衡器操作的接口. 动态更新一组服务列表及根据指定算法从现有服务器列表中选择一个服务
DynamicServerListLoadBalancer
DynamicServerListLoadBalancer 组合 Rule,IPing,ServerList,ServerListFilter,ServerListUpdater 实现类, 实现动态更新和过滤更新服务列表
ZoneAwareLoadBalancer
这是 DynamicServerListLoadBalancer 的子类, 主要加入 zone 的因素. 统计每个 zone 的平均请求的情况, 保证从所有 zone 选取对当前客户端服务最好的服务组列表
4. 通过属性文件配置 ribbon 的主要组件
除了可以使用编程方式创建外, ribbon 也提供通过反射和配置属性文件来实现对应的功能.
4.1. 根据属性文件配置 ribbon
配置属性的格式如下:
<clientName>.<nameSpace>.<propertyName>=<value>
. <clientName>: 这是调用 ribbon 的客户端名称, 如果此值为没有配置, 则此条属性会作用到所有的客户端.
. <nameSpace>: 默认值为 "ribbon"
. <propertyName>: 所有的可用的属性都在 com.netflix.client.conf.CommonClientConfigKey.
如果你没有配置任何属性, 则 ribbon 会使用 com.netflix.client.config.DefaultClientConfigImpl 里的值. 反之, 则会使用你配置的值替换默认的值
下面是对客户端名称为 "sample-client" 配置属性的 demo
# Max number of retries on the same server (excluding the first try)
sample-client.ribbon.MaxAutoRetries=1
# Max number of next servers to retry (excluding the first server)
sample-client.ribbon.MaxAutoRetriesNextServer=1
# Whether all operations can be retried for this client
sample-client.ribbon.OkToRetryOnAllOperations=true
# Interval to refresh the server list from the source
sample-client.ribbon.ServerListRefreshInterval=2000
# Connect timeout used by Apache HttpClient
sample-client.ribbon.ConnectTimeout=3000
# Read timeout used by Apache HttpClient
sample-client.ribbon.ReadTimeout=3000
# Initial list of servers, can be changed via Archaius dynamic property at runtime
sample-client.ribbon.listOfServers=www.microsoft.com:80,www.yahoo.com:80,www.google.com:80
4.2. 通过配置文件配置 Ribbon 的主要组件
使用以下属性值可以配置 ribbon 组合接口使用哪个具体的实现类, xx 表示类的全限定名称, 这里略:
<clientName>.<nameSpace>.NFLoadBalancerClassName=xx
<clientName>.<nameSpace>.NFLoadBalancerRuleClassName=xx
<clientName>.<nameSpace>.NFLoadBalancerPingClassName=xx
<clientName>.<nameSpace>.NIWSServerListClassName=xx
<clientName>.<nameSpace>.NIWSServerListFilterClassName=xx
4.3 Spring Cloud Netflix 提供默认的 ribbon 实现类
IClientConfig ribbonClientConfig: DefaultClientConfigImpl
IRule ribbonRule: ZoneAvoidanceRule
IPing ribbonPing: DummyPing
ServerList ribbonServerList: ConfigurationBasedServerList
ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter
ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer
ServerListUpdater ribbonServerListUpdater: PollingServerListUpdater
来源: https://juejin.im/entry/5a5f3beb6fb9a01cb42c658f