SpringCloud解析之Ribbon
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请求。
SpringCloud解析之Ribbon的更多相关文章
- SpringCloud学习之Ribbon
一.负载均衡与Ribbon 负载均衡,在集群中是很常见的一个“名词”,顾名思义是根据一定的算法将请求分摊至对应的服务节点上,常见的算法有如下几种: 轮询法:所有请求被依次分发到每台应用服务器上,每台服 ...
- SpringCloud解析之Zuul(二)
本文基于Spring Cloud Edgware.SR6,Zuul版本1.3.1,解析Zuul的请求拦截机制,让大家对Zuul的原理有个大概的认识和了解.如有不对的地方,欢迎指正. 在上一期的Spri ...
- SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]
目录 前提:本篇是基于 SpringCloud+Eureka+Feign+Ribbon的简化搭建流程和CRUD练习[1] 的修改与拓展 1.修改consumer的CenterFeign.java,把返 ...
- 【SpringCloud】Netflix源码解析之Ribbon:负载均衡策略的定义和实现
Ribbon负载均衡策略定义 IRule其实就只做了一件事情Server choose(Object key),可以看到这个功能是在LB中定义(要求)的,LB把这个功能委托给IRule来实现.不同的I ...
- SpringCloud | FeignClient和Ribbon重试机制区别与联系
在spring cloud体系项目中,引入的重试机制保证了高可用的同时,也会带来一些其它的问题,如幂等操作或一些没必要的重试. 今天就来分别分析一下 FeignClient 和 Ribbon 重试机制 ...
- SpringCloud学习(4)——Ribbon负载均衡
Ribbon概述 SpringCloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡工具. 简单的说, Ribbon是Netflix发布的开源项目, 主要功能是提供客户端软 ...
- SpringCloud 进阶之Ribbon和Feign(负载均衡)
1. Ribbon 负载均衡 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端,负载均衡的工具; 1.1 Ribbon 配置初步 1.1.1 修改 micros ...
- SpringCloud教程二:Ribbon(Finchley版)
在上一篇文章,讲了服务的注册和发现.在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的.Spring cloud有两种服务调用方式,一种是ribbon+r ...
- spring cloud深入学习(四)-----eureka源码解析、ribbon解析、声明式调用feign
基本概念 1.Registe 一一服务注册当eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,比如IP地址.端口.运行状况指标的Uri.主页地址 ...
随机推荐
- C# WebBrowser的使用
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
- 枚举与字符串转及RecordSet转XML,JSON
function AdoToJs(ado: TADOQuery): string; var I, J: Integer; json: string; begin json := '{columns:[ ...
- Win10《芒果TV》春季商店版更新v3.3.0:全新视觉蜕变&支持快男直播
在微软发布Win10创意者更新正式版前夕,Win10版<芒果TV>迅速更新至v3.3.0,主要是全新升级视觉交互,新增大咖快男个人直播,全面优化底层架构,启动大提速. Win10版< ...
- Windows Azure之Mobile Service
我建个android app和Windows Azure的Mobile Service配合,以实现会员注册的功能,实际十分简单,微软家的东西真心好用 首先新建个Mobile Service New-& ...
- windows qt 使用c++ posix接口编写多线程程序(真神奇)good
一.多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序.一般情况下,两种类型的多任务处理:基于进程和基于线程.基于进程的多任务处理是程序的并发执行.基于线程的多任务处理 ...
- 关于Eurekalog解决不能发邮件的问题
最近无意中发现在盒子论坛中有人回答了本文的问题,最后在Eurekalog的安装目录中的ExceptionLog.pas找到了多发送的Rest命令的地方,现传上来,有需要的朋友下载下面的文件. 因为16 ...
- QT---Winsocket获取网关(Gateway) 主机IP等信息
基于WinPcap库做开发,需要利用到局域网的默认网关地址和Mac地址,但是WinPcap实现获取网关IP地址没有很好的思路,可以知道的是网关的接收和发出的数据包数量一般是比局域网内的各主机要多的 ...
- ACL FAQ
acl 下载地址:https://sourceforge.net/projects/acl/https://github.com/zhengshuxin/acl/http://git.oschina. ...
- vue history 模式打包部署在域名的二级目录的配置指南
最近在做项目,需要把项目部署在域名下的二级目录,并且是在用vue-router的history 模式. 我们都知道vue-router 的两种前端基本访问模式 hash 和history .hash ...
- python bmp image injection
1. 将原BMP文件的第三,第四字节替换为\x2F\x2A, 对应js中的注释符号/*BMP文件的第三.四.五.六字节表示BMP文件的大小2. 在BMP文件末尾添加(1)\xFF(2)\x2A\x2F ...