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

注意:

1.RestTemplate 所在jar为:org.springframework.web.client.RestTemplate 说明了其并不依赖springcloud

2. 所以2个springboot项目其实是可以调用的,而并不需要依赖springCloud,如图:

product服务:

order服务:

浏览器访问order服务:

由此可见,服务间调用并不需要依赖springcloud组件,那么,这样调用会存在什么问题呢?

1.ip和端口需要我们在每个调用的接口都要写死

2.如果一个服务做了集群,这样也是只能调用写死的那个服务

解决方案:引入springCloud

改造下:product创建2个实例,架构图如下:

product1的配置:

product2的配置:

order服务自定义轮询算法调用product服务:

调用第一次:

调用第二次:

由此可以见,负载均衡策略已经实现

然而:我们还是要拼接ip和端口,如果我们想通过服务名(spring.application.name)去调用呢:

调用结果跟之前的是一致的,默认使用轮询负载均衡算法; 上面的例子虽然@LoadBalanced不是ribbon的依赖包,但请求过程中最后还是会依赖ribbon进行负载均衡

思考:上面的例子为何能通过http://product/get去访问,我们知道要访问一个服务必须知道Ip和端口,最终要变成http://ip地址:端口/get形式的url

猜想:

1. http://product/get 请求会被拦截

2. 通过http://product/get可以获取到服务名称为product

3. 通过服务名称product 可以获取服务列表

4. 通过服务列表,按照一定的算法获取一个服务,本质就是从一个list集合中获取一个服务,关键就是如何确定下标index

5. 通过服务拿到对应的IP和端口,然后重新构建url

一.解决第一个猜想:http://product/get被拦截,拦截器在哪里,又是什么时候跟restTemplate 扯上关系的

1.1 springboot自动装配机制的理解

1.2 根据springboot自动装配机制,我们找下spring-cloud-netflix-ribbon的源码,可以看到

查看内容:

由此可见,该类会被springboot自动装配,后续的源码分析都会围绕该类来走

1.3分析LoadBalancerAutoConfiguration该类

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration { @LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList(); //只有加了@LoadBalanced注解的RestTemplate就会加到该集合中 @Autowired(required = false)
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList(); @Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
return () -> restTemplateCustomizers.ifAvailable(customizers -> {
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
for (RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate); //遍历restTemplates,给其添加自定义信息
}
}
});
} @Bean
@ConditionalOnMissingBean
public LoadBalancerRequestFactory loadBalancerRequestFactory(
LoadBalancerClient loadBalancerClient) {
return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
} @Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
static class LoadBalancerInterceptorConfig { @Bean
public LoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory); //这个就是我们要找的拦截器了
} @Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list); //拦截器在这个里设置到restTempalte中的
};
} } //省略部分代码 }

下面我们看看RestTemplate类的继承结构

1.4 小结: springboot自动装配机制会对META-INF\spring.factories中key为EnableAutoConfiguration的类进行初始化,而ribbon和springcloud集成的文件中含有的类为:

org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration,该类初始化时会先初始化LoadBalancerAutoConfiguration,而LoadBalancerAutoConfiguration这个类是一个配置类,里面含有的@Bean注解的方法返回的类都会
被初始化和注入spring容器,该类会为含有@LoadBalanced注解的RestTemplate类添加拦截器,而拦截器最终会存到父类的一个集合中

之后流程debug调试:

二.解决猜想通过  http://product/get可以获取到服务名称为product

//此处省略部分过程

猜想三和猜想四解决:  通过服务名称product 可以获取服务列表,并通过服务列表取出一个服务

//获取服务列表和和从服务列表中取出一个服务,下一篇博客将会做详细的讲解

猜想五:通过获取的服务进行url重构:

继续调试:

//省略部分调用

至此可以发现,ribbon底层主要是将我们的服务名称替换为ip和端口

附加:RestTemplate的底层调用:

响应结果是如何转换成String的呢?

继续跟进


												

Ribbon源码分析(一)-- RestTemplate 以及自定义负载均衡算法的更多相关文章

  1. SpringCloud全家桶学习之客户端负载均衡及自定义负载均衡算法----Ribbon(三)

    一.Ribbon是什么? Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端  负载均衡的工具(这里区别于nginx的负载均衡).简单来说,Ribbon是Netf ...

  2. Ribbon,主要提供客户侧的软件负载均衡算法。

    Ribbon Ribbon,主要提供客户侧的软件负载均衡算法.Ribbon客户端组件提供一系列完善的配置选项,比如连接超时.重试.重试算法等.Ribbon内置可插拔.可定制的负载均衡组件.下面是用到的 ...

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

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

  4. [Abp vNext 源码分析] - 11. 用户的自定义参数与配置

    一.简要说明 文章信息: 基于的 ABP vNext 版本:1.0.0 创作日期:2019 年 10 月 23 日晚 更新日期:暂无 ABP vNext 针对用户可编辑的配置,提供了单独的 Volo. ...

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

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

  6. springmvc 源码分析(三) -- 自定义处理器映射器和自定义处理器适配器,以及自定义参数解析器 和错误跳转自定页面

    测试环境搭建: 本次搭建是基于springboot来实现的,代码在码云的链接:https://gitee.com/yangxioahui/thymeleaf.git DispatcherServlet ...

  7. ribbon源码分析

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

  8. Dubbo学习源码总结系列五--集群负载均衡

            Dubbo提供了哪些负载均衡机制?如何实现的?          LoadBalance接口:可以看出,通过SPI机制默认为RandomLoadBalance,生成的适配器类执行sel ...

  9. 读书笔记-Ribbon源码分析

    @LoadBalanced注解用来给RestTemplate做标记,以使用负载均衡的客户端来配置. 通过搜索LoadBalancerClient可以发现,LoadBalancerClient是Spri ...

随机推荐

  1. mysql事务级别和spring中应用

    一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有 ...

  2. 区块链入门到实战(23)之以太坊(Ethereum) – 虚拟机架构

    以太坊(Ethereum)网络中,定义了一组通用协议用于支持智能合约的运行,其核心便是以太坊(Ethereum)虚拟机. 下图解释了该架构: 开发人员使用Solidity等开发语言开发智能合约 源程序 ...

  3. 想学习SEO可以看哪些书籍

    http://www.wocaoseo.com/thread-28-1-1.html 除了一些常见的比如入门推荐<走进搜索引擎>和进阶推荐<这就是搜索引擎--核心技术详解>之外 ...

  4. Maxscript中渲染中文版Vray完成贴图(VrayCompleteMap)的方法

    Objbakeproperties = $.INodeBakeProperties; --选定对象的烘培节点 Prjbakeproperties = $.INodeBakeProjProperties ...

  5. Java使用POI的SXSSFWorkbook与HSSFWorkbook导出复杂表头

    一.HSSFWorkbook与SXSSFWorkbook的区别: HSSFWorkbook是对Excel2003以前的版本进行操作的,即后缀名为.xls SXSSFWorkbook时对Excel200 ...

  6. 目标检测中的IOU和CIOU原理讲解以及应用(附测试代码)

    上期讲解了目标检测中的三种数据增强的方法,这期我们讲讲目标检测中用来评估对象检测算法的IOU和CIOU的原理应用以及代码实现. 交并比IOU(Intersection over union) 在目标检 ...

  7. Activiti7 使用监听器分配任务人员

    视屏中老师说,一般没有人用但是我还是想试试 但是当我画图的时候,发现IDEA的那个listener监听器点不开,不知道是不是我下载的插件不对还是什么原因,所以就亲自写了,看看到时候不行就下载一个Ecl ...

  8. vue中实现后台管理路由标签页

    <template> <section> <div class="navTabList el-tabs__nav-scroll" id="t ...

  9. Python基础 读取二进制文件

    问题 有二进制文件中保存了 20 亿个 2 Bytes 的数,需将其读出,每 20000 个数作图,拟合后输出结果. 解决 # -*- coding: utf-8 -*- ""&q ...

  10. pythont多线程

    import threading # 线程模块 def function(num): pass thread_1 = threading.Thread(target=function, args=(1 ...