读书笔记-Ribbon源码分析
@LoadBalanced注解用来给RestTemplate做标记,以使用负载均衡的客户端来配置。
通过搜索LoadBalancerClient可以发现,LoadBalancerClient是SpringCloud定义的一个接口
public interface LoadBalancerClient {
Serviceinstance choose(String serviceId);
<T> T execute(String serviceid, LoadBalancerRequest<T> request) throws
IOException;
URI reconstructURI(Serviceinstance instance, URI original);
}
通过该接口,了解客户端负载均衡器因该具备几种能力。
1.choose(String serviceId):根据传入的服务名serviceId,从负载均衡器中挑选一个对应的服务实例。
2.<T> T execute(String serviceid, LoadBalancerRequest<T> request):使用从负载均衡器中挑选服务实例来执行请求内容。
3.URI reconstructURI(Serviceinstance instance, URI original);:为系统构建一个合适的host:port形式的URI。在分布式系统中,我们使用逻辑上的服务名作为host来构建URI进行请求 。
LoadBalancerAutoConfiguration 类为实现客户端负载均衡的自动化配置类。通过查看配置类的源码。可以知道Ribbon实现的负载均衡自动化配置需要满足下面两个条件。
1.RestTemplate类必须存在于当前工程的环境中。
2.在Spring的Bean工程中必须有LoadBalancerClient的实现的Bean。
在改自动化配置类中,主要做了下面三个事:
1.创建了一个LoadBalancerInterceptor的Bean,用于实现客户端发起请求进行拦截,以实现客户端的负载均衡。
2.创建一个RestTemplateCustomizer的Bean,用于给RestTemplate增加LoadBalancerInterceptor拦截器。
3.维护了一个被@LoadBalanced注释修饰的RestTemplate对象列表。并在这里进行初始化,通过调用RestTemplateCustomizer的实例来给需要客户端负载均衡的RestTemplate增加LoadBalancerInterceptor拦截器。
通过源码分析,拦截器注入了LoadBalancerClient的实现,当一个被@LoadBalanced注解修饰的RestTemplate对象想外发起HTTP请求时,会被LoadBalancerInterceptor类的intercept函数所拦截。由于我们在使用RestTemplate时采用了服务名作为host,所以直接从HttpRequest的URI对象中通过getHost()就可以拿到服务名。然后调用execute函数去根据服务名来选择实例并发起实际的请求。
以上的LoadBalancerClient还只是一个抽象的负载均衡器接口,所以我们还需要找到他的具体实现类来进一步进行分析。他的具体实现类是RibbonLoadBalancerClient。
在RibbonLoadBalancerClient的execute函数实现中,第一步就是通过getServer根据传入的服务名serviceId去获得具体的服务实例。
SpringCloud默认财通了ZoneAwareLoadBalancer来实现负载均衡器。
通过ZoneAwareLoadBalancer的chooseServer函数获取了负载均衡策略分配到的服务实例对象Server之后,还将起对象包装成RibbonServer对象(该对象处理存储了服务实例的对象之外,还增加了服务名serviceId,是否需要使用HTTPS等其他信息),然后使用该对象在回调LoadBalancerInterceptor请求拦截器中LoadBalancerRequest的apply函数,向一个世纪的具体服务实例发起请求,从而实现一开始以服务名为host的URI请求到host:post形式的实际访问地址的转换。
在apply函数中传入的ServiceInstance接口对象是对服务实例的抽象定义,在改接口暴露了服务治理系统中每个服务实例需要提供的一些基本信息。比如serviceId,host,post等,具体定义如下。
public interface ServiceInstance {
String getServiceId();
String getHost();
int getPort();
boolean isSecure();
URI getUri();
Map<String, String> getMetadata();
}
上面提到的具体包装Server服务实例的RibbonServer对象就是ServiceInstance接口的实现,可以看到他除了包装Server对象之外,还存储了服务名,是否使用HTTPS标识以及一个Map类型的元数据集合。
从apply的实现中,可以看到他具体执行的时候,还传入了ServiceRequestWrapper对象,该对象继承了HttpRequestWrapper并重写了getURI函数,重写后的getURI通过调用LoadBalancerClient接口的reconstructURI函数来重新构建一个URI来进行访问。
读书笔记-Ribbon源码分析的更多相关文章
- Nginx学习笔记4 源码分析
Nginx学习笔记(四) 源码分析 源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_ ...
- Ribbon源码分析(二)-- 服务列表的获取和负载均衡算法分析
上一篇博客(https://www.cnblogs.com/yangxiaohui227/p/12614343.html)分享了ribbon如何实现对http://product/info/这个链接重 ...
- Ribbon源码分析(一)-- RestTemplate 以及自定义负载均衡算法
如果只是想看ribbon的自定义负载均衡配置,请查看: https://www.cnblogs.com/yangxiaohui227/p/13186004.html 注意: 1.RestTemplat ...
- Spring Cloud Ribbon 源码分析---负载均衡算法
上一篇分析了Ribbon如何发送出去一个自带负载均衡效果的HTTP请求,本节就重点分析各个算法都是如何实现. 负载均衡整体是从IRule进去的: public interface IRule{ /* ...
- ribbon源码分析
对于ribbon的使用我们只需要在RestTemplate的申明上面加上 @LoadBalanced 注解之后那么这个RestTemplate就具有了负载均衡的功能 ribbon是怎么实现这一功能的? ...
- 【黑客免杀攻防】读书笔记15 - 源码免杀、C++壳的编写
1.源码免杀 1.1 定位产生特征的源码 定位文件特征 1.根据MyCCL的特征码定位工具,定位出有特征的地址 2.根据VS的反汇编窗口,输入有特征的地址得到特征地址与源码的关系 3.插入Messag ...
- Spring Cloud Ribbon源码分析---负载均衡实现
上一篇结合 Eureka 和 Ribbon 搭建了服务注册中心,利用Ribbon实现了可配置负载均衡的服务调用.这一篇我们来分析Ribbon实现负载均衡的过程. 从 @LoadBalanced入手 还 ...
- ActiveMQ笔记:源码分析
本文对ActiveMQ的启动过程,以及BrokerService,TransportConnector和NetworkConnector等几个重要的模块的代码做一个简要的分析. 启动过程 如果要快速地 ...
- odoo开发笔记--定时任务源码分析
场景描述: 处理思路: 参考文章: 定时任务相关: https://www.jianshu.com/p/ad48239f84d6 https://blog.csdn.net/M0relia/artic ...
随机推荐
- Eclipse插件--一次copy多个文件的相对路径路径
因为工作需要, 在网上找了很多插件, 本来有个easyTools应该可以, 但下载文件好像没了. 只好自己动手搞了一个简单的, 暂时一个复制文件相对路径的功能, 有同样需求的童鞋, 可以试一下 plu ...
- sqlserver建立相同的表结构
select * into purpose from source 来自为知笔记(Wiz)
- eclipse添加tomcat运行时
方法一:添加jar包 方法二配置依赖 比如缺少javax.servlet.http.HttpServlet,ctrol+shift+t查找这个包 <dependencies> <de ...
- leetcode每日一题——反转整数
题目: 反转整数 难度: 简单 描述: 给定一个 32 位有符号整数,将整数中的数字进行反转. 解法: class Solution { public int reverse(int x) { //i ...
- python进阶——进程/线程/协程
1 python线程 python中Threading模块用于提供线程相关的操作,线程是应用程序中执行的最小单元. #!/usr/bin/env python # -*- coding:utf-8 - ...
- Silverlight中获取控件中子控件
如题:,直接来看代码: /// <summary> /// 查找并返回第一个 相同 name的子元素 /// </summary> /// <typeparam name ...
- 关于获得MFC窗口其它类指针的方法(csdn)
转自:http://tieba.baidu.com/p/252804018 访问应用程序的其它类 获得CWinApp: -在CMainFrame,CChildFrame,CDocument,CView ...
- Web开发相关笔记 #01#
前端学习纲要 ※jQuery 参考 ※ 整理 Chrome 收藏夹的小技巧 ※ 解决 AJAX 跨域获取 cookie ※ 记一次 MyBatis 相关的 debug [1] 前端学习纲要: ♦ 第一 ...
- docker 在windows上的使用
Docker ToolBox 安装 1.首先,安装Docker ToolBox,其中包含了Docker三剑客: docker , docker-machine 和 docker-compose . 安 ...
- Python 面向对象的三大特性:封装,继承,多态
# 面向对象的三大特性:封装,继承,多态 # 继承的影响:资源的继承,资源的使用,资源的覆盖,资源的累加 # 资源的继承,在Python中的继承是指能使用父类的资源,而不是说在子类也复制一份父类代码到 ...