Ribbon是分布式微服务架构中负载均衡的一个解决方案,我们只需要引入ribbon依赖,然后初始化一个RestTemplate对象,在其上添加@LoadBalanced注解,就可以实现请求的负载均衡,像下面这样

RestTemplate是属于org.springframework.web.client包下,那么它是如何通过ribbon实现负载均衡的呢?
SpringBoot在启动时会加载spring-cloud-commons.jar中的一些自动化配置文件,其中有LoadBalancerAutoConfiguration,看名字大家可以猜到这个是负载平衡自动配置文件。
首先,它会将所有程序中有@LoadBalanced注解的RestTemplate实例放入一个集合,
然后创建一个负载平衡请求工厂LoadBalancerRequestFactory,这里传入的loadBalancerClient,其实是ribbon的RibbonLoadBalancerClient,它实现了
LoadBalancerClient接口
接着创建一个负载平衡拦截器LoadBalancerInterceptor,这里传入的就是上面的RibbonLoadBalancerClient和LoadBalancerRequestFactory

然后,遍历RestTemplate集合,给每一个RestTemplate实例添加上面创建好的LoadBalancerInterceptor

总结起来,LoadBalancerAutoConfiguration就是给所有@LoadBalanced注解的RestTemplate装上一个负载平衡拦截器LoadBalancerInterceptor。

之后,当发起请求执行restTemplate方法时,最后是执行的内部的doExecute方法,它创建的ClientHttpRequest其实是实现类InterceptingClientHttpRequest,最终调用的是InterceptingClientHttpRequest的内部类InterceptingRequestExecution的execute方法

这里,从拦截器的迭代器中取出的ClientHttpRequestInterceptor,其实是它的实现LoadBalancerInterceptor,这就是在LoadBalancerAutoConfiguration中set进去的,然后执行LoadBalancerInterceptor的intercept方法

在LoadBalancerInterceptor中,最后执行的loadBalancer.execute,是RibbonLoadBalancerClient的方法,别忘了,在LoadBalancerAutoConfiguration中创建的负载平衡拦截器LoadBalancerInterceptor,传入的初始化参数就是RibbonLoadBalancerClient

RibbonLoadBalancerClient.execute方法中,首先会根据serviceId获取负载平衡拦截器,然后将其传入getServer方法中

这里其实还是调用的拦截器的chooseServer方法,

最后,调用rule.choose方法,这里的rule是ribbon的负载平衡规则,ribbon的负载平衡规则有轮询,随机,响应时间权重,空闲这么几种,默认是轮询,可以通过配置指定规则,比如配置成权重MY-PROVIDER.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.WeightedResponseTimeRule

(具体每一种规则的逻辑就不在此细说,有兴趣的朋友可以自行查阅)。根据负载平衡规则获取到具体的Server实例后,将Server包装成RibbonServer,

继续走,

终于,最后,执行的是request.apply方法,这里的request就是LoadBalancerInterceptor.intercept方法中LoadBalancerRequestFactory.createRequest方法创建的request

跟着request.apply方法进来,发现将request包装成了ServiceRequestWrapper,但是这里并没有使用ribbon负载平衡后获取的服务实例instance,接着走,

发现又回到了InterceptingClientHttpRequest的内部类InterceptingRequestExecution的execute方法,

这时已经没有拦截器了,走到else中,要创建一个ClientHttpRequest,createRequest(request.getURI(), request.getMethod())中的request是上面的

ServiceRequestWrapper,我们看下它的getURI()逻辑

原来是在这里,调用了RibbonLoadBalancerClient.reconstructURI方法,在内部通过负载平衡获取的服务实例组装成具体的uri,在之后就是常规操作了,拼接请求头和请求参数,发起请求。

绕了一大圈,做下总结:

添加了@LoadBalanced注解的RestTemplate执行时,会进入LoadBalancerInterceptor的intercept方法,接着会进入ribbon的RibbonLoadBalancerClient类,在该类中通过serviceId获取负载平衡器,然后通过其内部的负载平衡规则获取具体的Server实例,最后回到InterceptingClientHttpRequest.execute方法,通过包装的ServiceRequestWrapper.getURI()方法,调用RibbonLoadBalancerClient.reconstructURI方法拼接具体的请求uri,然后执行http请求。

最新文章

  1. WPF 通过Border来画边框
  2. Spring MVC重定向和转发及异常处理
  3. 关于iis8.5中发布的网站无法连接数据库的解决方案。
  4. 一场属于HTML5守望者的盛宴——记图灵参加HTML5峰会
  5. Atitit 桌面软件跨平台gui解决方案 javafx webview
  6. (转载)ecshop制作成手机网站的方法
  7. CodeTimer
  8. JAVA简单的UI设计
  9. 在java中生成二维码,并直接输出到jsp页面
  10. angularJS之ng-repeat
  11. eclipse中git解决冲突
  12. React Native组件只Image
  13. 使用脚本调用maven命令后脚本直接退出问题
  14. 1test
  15. Splay简介
  16. Struts2乱码问题的解决办法
  17. JQuery 简单表格验证
  18. Web程序中打开QQ、邮箱、阿里旺旺等
  19. Frequently-Used Network Time Server(Base On NTP:Network Time Protocol)
  20. VMware Workstation 虚拟机纯 Linux 终端如何安装 VMware Tools ?

热门文章

  1. WCF调试日志
  2. CSS visibility 属性 使元素占位,但不可见
  3. php判断是否是移动设备
  4. 图像滤镜艺术---挤压(Pinch)滤镜
  5. 有未经处理的异常(在 xx.exe 中): 堆栈 Cookie 检测代码检测到基于堆栈的缓冲区溢出。
  6. Windows 10 UWP 部署
  7. Android应用开机自启动问题
  8. C# winform 主界面打开并关闭登录界面
  9. Qt通过HTTP POST上传文件(python做服务端,附下载)
  10. 事务 ( 进程 ID 60) 与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品