在看网文或《spring cloud微服务实战》(以下简称:实战)时,发觉对spring cloud Netflix ribbon的描述容易陷入细节,初学者看的晕乎。本人重新看了实战、网文和spring cloud ribbon相关代码,终于理清其思路,随写下备忘笔记。
《金字塔原理》说要表达一个事情,结论先行是最好的方式。因此理解spring cloud Netflix ribbon源码,最好是先理解它设计初衷(思考:假设是自己设计,会怎么做)。
spring cloud Netflix ribbon作用是利用Netflix的ribbon组件实现客户端负载均衡(以下简称:CLB),即 = Spring cloud + ribbon。作为Spring cloud的设计者,显然不想紧耦合ribbon;反之亦然。而网友把Spring cloud和ribbon揉在一起描述,是让人晕乎的原因。
很自然的,假设我们设计Spring cloud的CLB 和 ribbon,顶层思路是要考虑这几个事情:
1. 设计spring cloud自己的通用CLB接口,用于调用第三方的CLB组件
2. 设计ribbon(第三方的CLB组件)接口:定义作为客户端负载均衡器应有的operations
3. 利用适配器,装饰器(或wrapper)之类的模式将spring cloud与ribbon对接起来。
4. 在服务间通信的组件(如:Resttemplate)中,放入CLB的调用
OK,开始干活。
1. 我们设计名为LoadBalancerClient的接口,作为Spring cloud CLB通用接口类,里面应该有这样的接口函数:接收请求,并从服务实例列表挑选一个作为请求接收方;
2. 设计ribbon接口类:ILoadBalancer, 一个最简单的LB的至少有点功能:设置添加和读取后端的服务(器)列表;能从中选择一个服务(器)
3. 同时提供一个LoadBalancerClient实现类将上面的两者整合适配:RibbonLoadBalancerClient.
4. 用耦合度最低的方式:往客户端发起请求的地方(Resttemplate)增加一个拦截器,拦截器中调用LoadBalancerClient的bean(RibbonLoadBalancerClient)实现CLB功能。增加拦截器这个动作,最好能自动完成,熟悉Spring boot的同学会很快想到,用autoconfig(LoadBalancerAutoConfiguration):
上面是设计者的顶层设计,接下来要对每个接口的实现进行设计(很像金字塔原理)。
Cloud侧接口LoadBalancerClient的设计:参看源码或《实战》、网文
Cloud侧RibbonLoadBalancerClient:既然是适配、包装,则免不了1)调用ribbon的服务实例选择接口(chooseServer),2)然后包装一下返回的的服务实例(用RibbonServer),用于保存url,port之外的HTTPS,元数据等信息 3)根据实例信息重构具体请求要送达的url(reconstructURI) 4)同时在做些统计之类的事情(用RibbonStatsRecorder工具,ribbon已经做了统计,这里为何要统计?我没搞清楚)
Cloud侧LoadBalancerInterceptor:参考源码或《实战》
ribbon侧ILoadBalancer等详细设计:CLB的具体实现逻辑都在这里,因此好好斟酌一下,如果是我们设计,应该包含哪些特性:
1)维护一个server(服务提供方)的列表:server list,获取方式可配
2)可动态更新server list,更新策略可配
3)可监测server list的可用性:监测方法可配
4)可配置多个负载均衡策略
5)可过滤部分servers:过滤规则也是可配
根据所想要的特想, 不难设计如下类图(暂时先不用看接口实现):
IClientConfig,IRule,IPing,ServerLis,ServerListFilter,ServerListUpdater几个接口分别实现了上述设计特性。最基础的实现类是BaseLoadBalancer,DynamicServerListLoadBalancer和ZoneAwareLoadBalancer(上图未列出)只是扩展了他的功能。
未完待续...后续将写上更详细的源码阅读随笔和基于ribbon的自定义灰度发布功能实现