Robin负载均衡策略存在问题及CSE解决方案

Robin

Robin设计了几个核心接口:IRule、ILoadBalancer、ServerListFilter、IPing、ServerList、Server。开发者在使用的时候,需要组合使用这些接口。Robin提供了大量的接口实现,在使用这些实现或者自定义实现的时候,存在非常多的问题需要考虑:

1

每一个实现类依赖的其他接口的功能是不确定的,不能够随意组合。比如:ServerListFilter只会被DynamicServerListLoadBalancer使用,而不会被ILoadBalancer的其他实现类使用;IRule的不同实现,依赖的ILoadBalancer接口不同,RoundRobinRule会调用getAllServerList,并且会判断返回的Server是否alive,而RandomRule则不会使用这些接口,这种情况会给实现ILoadBalancer的开发人员带来大量的困扰,他们必须对每一个可能的IRule实现进行测试,以保证提供给用户的功能说明是可靠的。这种情况带来的另外问题,就是限制了运维人员在运行时动态的调整负载均衡策略。使用Robin组件,更加适用于开发阶段确定好各个实现,而不进行修改。

2

在使用ServerListFilter的时候,不能够基于每次请求的参数进行实例过滤。这样类似灰度发布等功能无法通过它实现。因为ServerListFilter会通过ILoadBalancer获取当前请求参数,而ILoadBalancer则被大量的请求共用。业务必须通过ThreadLocal来保存请求参数,以防止并发问题。初次使用这种机制的业务基本都会忽略这个问题,必须通过大量并发测试才可能发现,很多时候会将问题遗漏到生产环境。

3

在需要动态调整IRule的场景,部分IRule的实现可能会导致内存泄露。比如WeightedResponseTimeRule。这个规则在初始化的时候,会启动Timer线程计算权重,并且每次更新ILoadBalancer的时候(调用setLoadBalancer方法),会重新初始化,如果并发控制不当,则会导致频繁创建线程造成OOM。这个问题需要在进行大量并发和持续运行的情况下才能够发现。

总结:Robin定义了很灵活的接口,在实现单一场景的时候,可以满足非常多场景的需求。但是在动态调整策略、自由组合策略以及定制开发过程中都存在大量的陷阱,需要开发人员非常谨慎使用,有些陷阱需要进行大量并发和长时间运行才能够发现。

CSE对负载均衡算法的改进

CSE结合自身对负载均衡的理解,对负载均衡处理流程进行了改进。下面是流程图:

1

DiscoveryFilter主要管理实例进行分组、缓存。详细流程参考:https://docs.servicecomb.io/java-chassis/zh_CN/references-handlers/loadbalance.html

2

对每一个微服务分配一个LoadBalancer实例。

3

ServerListFilerExt和RuleExt均对Robin的ServerListFilter和IRule进行了改进。参数增加了Invocation,这样可以支持基于接口参数的路由选择。对于ServerListFilter和IRule的扩展,都只需要实现接口,并不需要依赖大量的LoadBalancer的接口,这样就避免了业务在实现这些接口的时候,需要考虑组合的一致性,减少业务犯错误的风险。

4

整改以后,业务不能在随意配置和使用IRule和ServerListFilter的实现。需要使用系统缺省的配置参数:RoundRobin、Random、SessionStickiness、WeightedResponse等,这些字符串表达和实现方式独立。业务也可以通过扩展ExtensionFactory实现自己的RuleExt和ServerListFilterExt。

基于响应时间权重问题

经过上述整改,CSE重新实现了WeightedResponseTimeRule,新实现的算法没有采用定时器和新线程,可以避免频繁替换Rule和并发场景下可能导致的内存泄露等问题。这个算法存在如下需要注意的问题:

1

“权重”和“响应时间”并不是一个严格意义上的反比关系。比如时延为20ms和40ms,并不意味着实例选择的概率是2:1。目前计算“权重”和“响应时间”的算法为:

T = SUM(L1,L2,…,Ln)

(L1:L2:…:Ln) = (T-L1:T-L2:…:T-Ln)=(W1:W2:…:Wn)

“权重算法”是一个伪随机算法,实例的分布符合上述的公式,但是每次选中的实例是不可预期的。 另外,如果所有实例的响应时间均小于10ms,那么权重算法等同于RoundRobin算法。

2

在实例数为100的情况下,基于响应时间权重算法比RoundRobin算法慢100倍。但是不用担心,这个是对实例列表遍历一遍的时间,在业务处理时间为10ms的情况下,只占用业务1/1000的时间。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181025G1IQH500?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券