前面我们学习了Ribbon的7种内置负载均衡策略,那么大家知道是谁在这中间牵线搭桥,把配置的负载均衡策略“加塞”到一个HTTP请求的调用链路里的吗?这就要讲到Ribbon对RestTemplate的改造。
之前我们搭建了自己的ribbon-consumer,大家都知道Ribbon通过RestTemplate来发起调用请求。可是,RestTemplate分明是spring-web包下的通用类,它诞生的时候Ribbon还不知道在哪儿呢,那Ribbon是如何实现偷天换日,悄悄把自己“加塞”到RestTemplate中去的呢?

传送门 - @LoadBalanced

老师在上学的时候很喜欢玩一款叫《英雄无敌》的游戏,这是一个魔法战争的游戏,充满着魔幻神秘色彩。这个游戏里有一个叫做“传送门”的机关,当你控制的英雄进入传送门的时候,他便会从另一个世界的另一扇门中出现。
当上帝为你关上一扇门的时候,也会为你开启另一扇门。Ribbon也有这么一个魔法门,就是@LoadBalanced注解,它会将RestTemplate传送到Ribbon的自动装配类里进行改造。我们来看下它是怎么做的:
负载均衡器LoadBalancer原理解析 - 图1

  • @LoadBalanced 这个注解一头挂在RestTemplate上,另一头挂在LoadBalancerAutoConfiguration这个类上。它就像连接两个世界的传送门,将所有顶着「LoadBalanced」注解的RestTemplate类,都传入到LoadBalancerAutoConfiguration中。如果要深挖底层的作用机制,大家可以发现这个注解的定义上还有一个@Qualifier注解,可能对Spring比较熟悉的同学就恍然大悟了。@Qualifier注解搭配@Autowired注解做自动装配,可以通过name属性,将指定的Bean装载到指定位置(即使有两个同样类型的Bean,也可以通过Qualifier定义时声明的name做区分)。这里「LoadBalanced」也是借助Qualifier实现了一个给RestTemplate打标签的功能,凡是被打标的RestTemplate都会被传送到AutoConfig中做进一步改造。
  • LBAutoConfig 从前一步中传送过来的RestTemplate,会经过LBAutoConfig的装配,将一系列的Interceptor(拦截器)添加到RestTemplate中。拦截器是类似职责链编程模型的结构,我们常见的ServletFilter,权限控制器等,都是类似的模式。Ribbon拦截器会拦截每个网络请求做一番处理,在这个过程中拦截器会找到对应的LoadBalancer对HTTP请求进行接管,接着LoadBalancer就会找到默认或指定的负载均衡策略来对HTTP请求进行转发。

总结Ribbon的作用机制就是,由LoadBalanced在RestTemplate上打标,Ribbon将带有负载均衡能力的拦截器注入标记好的RestTemplate中,以此实现了负载均衡。在稍后的源码阅读章节,将带大家深入研究LoadBalanced注解的作用机制。

没事看电视 - IPing机制

负载均衡器LoadBalancer原理解析 - 图2
在计划生育实施的初期,效果并不好,因为那时候没有如今各种丰富的娱乐活动,大家下了班都闲着没事干,闲着没事那就只好造人了。后来有个村支书想了个法子,他给每家配了一台电视机,这样一来每家每户晚上就有事情可干了,超生指标立马就降下来了。这说明了一个问题,闲着没事就得要找点事干。
Ribbon也正面临这么个问题,和其它SpringCloud组件相比,Ribbon可谓称得上闲差,因为它的职责相对单一,只应用在负载均衡方面,说明它太闲了,所以这才要给Ribbon找点事儿干。
IPing机制就是SpringCloud发给Ribbon家的电视机,那它放哪些电视节目呢?现在请收看电视节目《撩妹指南》
负载均衡器LoadBalancer原理解析 - 图3
IPing是一个主动出击撩妹子的机制,他主动判断服务节点的当前状态,决定是否可作为目标节点,只有当前可用的节点才会作为负载均衡器的目标节点。IPing有以下几个撩妹手段:

  • 自娱自乐式:DummyPing,默认返回true,即认为所有节点都可用,这也是单独使用Ribbon时的默认模式
  • 隔山打牛式:NIWSDiscoveryPing,借助Eureka服务发现机制获取节点状态,假如节点状态是UP则认为是可用状态
  • 主动出击式:PingUrl,这才是真正走出家门去撩妹,它会主动向服务节点发起一次http调用,如果对方有响应则认为节点可用

大家可以看出第三种主动出击的模式比较生猛,IPing就像一条脱缰的野狗一样,对每个服务节点撩个不停,节点们纷纷表示扛不住扛不住。大家可以想象,假如我们的服务节点搭载的是淘宝ump服务(负责计算商品、购物车与订单优惠,淘系top5调用量),ump下随便一个微服务都有大几千台服务器,在服务本身就被超高访问量调用的情况下,那这种主动出击的IPing策略必然会大大增加服务节点的访问压力。
既然Eureka已经有了服务发现机制,可以获取节点的当前状态,拿来就用岂不更好?因此,除非特殊指定,在和Eureka搭配使用的时候,采用的是第二种隔山打牛式,也就是过滤非UP状态的节点(其实这个功能直接放Eureka里也能做。。。看来真的是没事给Ribbon找点事)

小结

今天我们学习了LoadBalanced注解的作用机制和IPing的工作模式,下一小节将带大家近距离研究LoadBalanced的源码。
学习心得tips: 当我们对一项技术进行系统的学习,学到会用的程度,这只能算作是入了门(简历上可以写了解xxx技术)。当你深入研究源码,理解了底层原理的时候,这时候算得上是“上得厅堂”(简历上可以写熟悉xxx技术)。当你达到可以定制、改造框架组件,满足自己特殊应用场景的时候,那便也下得厨房了(简历上可以写精通)。所以,老师每次碰到简历上写精通xxx等技术的同学,基本都没过得了面试关,因为我对他的所“精通”的技术会有很高的期望,自然会深挖最底层的技术细节和实现方式,或者让面试者谈谈如果自己实现这套机制打算如何设计。所以说简历可以适当粉饰,但是千万不要过头了,不然可能会适得其反。当然,如果作为5年以上的技术人员,依然停留在“熟悉”的阶段,那便要抓紧往前追赶了。