@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源码分析的更多相关文章

  1. Nginx学习笔记4 源码分析

    Nginx学习笔记(四) 源码分析 源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_ ...

  2. Ribbon源码分析(二)-- 服务列表的获取和负载均衡算法分析

    上一篇博客(https://www.cnblogs.com/yangxiaohui227/p/12614343.html)分享了ribbon如何实现对http://product/info/这个链接重 ...

  3. Ribbon源码分析(一)-- RestTemplate 以及自定义负载均衡算法

    如果只是想看ribbon的自定义负载均衡配置,请查看: https://www.cnblogs.com/yangxiaohui227/p/13186004.html 注意: 1.RestTemplat ...

  4. Spring Cloud Ribbon 源码分析---负载均衡算法

    上一篇分析了Ribbon如何发送出去一个自带负载均衡效果的HTTP请求,本节就重点分析各个算法都是如何实现. 负载均衡整体是从IRule进去的: public interface IRule{ /* ...

  5. ribbon源码分析

    对于ribbon的使用我们只需要在RestTemplate的申明上面加上 @LoadBalanced 注解之后那么这个RestTemplate就具有了负载均衡的功能 ribbon是怎么实现这一功能的? ...

  6. 【黑客免杀攻防】读书笔记15 - 源码免杀、C++壳的编写

    1.源码免杀 1.1 定位产生特征的源码 定位文件特征 1.根据MyCCL的特征码定位工具,定位出有特征的地址 2.根据VS的反汇编窗口,输入有特征的地址得到特征地址与源码的关系 3.插入Messag ...

  7. Spring Cloud Ribbon源码分析---负载均衡实现

    上一篇结合 Eureka 和 Ribbon 搭建了服务注册中心,利用Ribbon实现了可配置负载均衡的服务调用.这一篇我们来分析Ribbon实现负载均衡的过程. 从 @LoadBalanced入手 还 ...

  8. ActiveMQ笔记:源码分析

    本文对ActiveMQ的启动过程,以及BrokerService,TransportConnector和NetworkConnector等几个重要的模块的代码做一个简要的分析. 启动过程 如果要快速地 ...

  9. odoo开发笔记--定时任务源码分析

    场景描述: 处理思路: 参考文章: 定时任务相关: https://www.jianshu.com/p/ad48239f84d6 https://blog.csdn.net/M0relia/artic ...

随机推荐

  1. python16_day06【类、RE模块、subprocess模块、xml模块、shelve模块】

    一.shelve模块 import shelve # 基于pickle模块, d = shelve.open('shelve_test') class Test(object): def __init ...

  2. Bootstrap实现的页面

    实现的效果如图,使用bootstrap需要至少三个文件 去bootstrap网上下载,然后使用这三个文件可以了 使用方式,通过标签,class命名来引用已经定制好的html样式 <!DOCTYP ...

  3. 练Focus T25必看!T25课表 视频与成功案例汇总

    练Focus T25必看!T25课表 视频与成功案例汇总! [复制链接]  http://jianfei.39.net/thread-3645799-1.html     小西i减肥         ...

  4. CNN学习笔记:梯度下降法

    CNN学习笔记:梯度下降法 梯度下降法 梯度下降法用于找到使损失函数尽可能小的w和b,如下图所示,J(w,b)损失函数是一个在水平轴w和b上面的曲面,曲面的高度表示了损失函数在某一个点的值

  5. CNN学习笔记:线性回归

    CNN学习笔记:Logistic回归 线性回归 二分类问题 Logistic回归是一个用于二分分类的算法,比如我们有一张图片,判断其是否为一张猫图,为猫输出1,否则输出0. 基本术语 进行机器学习,首 ...

  6. MAC brew软件安装

    之前一直怀念ubuntu下的apt-get,因为实在是方便,需要安装什么,一个命令搞定,相关的依赖包统统由apt-get维护.下载,编译,安装,那叫一个痛快.什么软件用着不爽,一个命令卸载! 怀念ap ...

  7. form表单4种提交方式

    <!DOCTYPE html><html> <head> <title>JavaScript表单提交四种方式</title> <met ...

  8. HDU 3966 Aragorn's Story (树链剖分入门题)

    树上路径区间更新,单点查询. 线段树和树状数组都可以用于本题的维护. 线段树: #include<cstdio> #include<iostream> #include< ...

  9. phpword使用

    composer 安装 https://packagist.org/packages/phpoffice/phpword 开发文档:http://phpword.readthedocs.io/en/l ...

  10. 【笔记】IntelliJ IDEA配置Hibernate

    参考:imooc:http://www.imooc.com/video/7706 1.创建Hibernate的配置文件. 将依赖包导入项目.http://blog.csdn.net/a15337525 ...