文章目录

  • 一、前言
  • 二、远程调用的基础,RestTemplate封装Http请求
  • 三、Ribbon负载均衡的使用
    • 3.1 Ribbon负载均衡的原理
    • 3.2 Ribbon负载均衡的实现
  • 四、Ribbon源码解析
    • 4.1 初始化三个bean,拦截所有带有@LoadBalance注解的RestTemplate
      • 4.1.1 拦截器的引入
      • 4.1.2 @Qualifier注解
      • 4.1.3 初始化三个bean,拦截所有带有@LoadBalance注解的RestTemplate
    • 4.2 获得所有拦截住的LoadBalancer,再根据LoadBalancer获得到具体的Server,实现负载均衡
      • 4.2.1 进入拦截器中
      • 4.2.2 根据serviceId得到具体的负载均衡器
      • 4.2.3 根据负载均衡器得到具体的服务器
      • 4.2.4 生成RibbonServer并执行
  • 五、尾声

一、前言

ribbon是一个顶级渣男,也是一个顶级时间管理大师,他有100个女朋友,但是这100个女朋友相互之间并不知道,因为ribbon每次都邀请一个女朋友约会,坚决不要各个女朋友认识。

ribbon手里有各个女朋友的电话号码、微信号、家庭住址和家庭成员信息,永远不会搞错,ribbon每晚上约会一个女朋友,他是怎样选择的呢?他有各种方案,可以给女朋友编号,从1号到100号,这样的话,连续三个月都不换重的,爽乖乖;可以每天晚上翻牌子,随便抽取一个,好有古代皇帝的感觉;也可以尽量邀请那些约会不要让他等他久女孩子,毕竟渣男是时间宝贵。

本文,手把手教你ribbon如何轻松应对100个女朋友的约会的情场秘籍。

二、远程调用的基础,RestTemplate封装Http请求

Spring Cloud分为两个部分,分别是Spring Cloud Netflix和Spring Cloud Alibaba。其中,

Spring Cloud Netflix: Ribbon、Hystrix、Feign、Eureka等;

Spring Cloud Alibaba:dubbo、nacos注册中心、seata、rocketMQ消息队列、sentinel等。

单体架构中,整个项目部署到Linux就是一个war包,但是由于业务量的增加,整个软件系统部署到一个服务器,硬件资源撑不起这么大的业务访问量,所以引入了微服务架构。

对于微服务架构,将整个软件系统拆分为不同的服务,每一个服务部署到Linux上就一个war包,服务与服务之间的通信就是微服务通信。

所以,正是因为业务量的增加引入了微服务架构,因为引入了微服务架构不可避免地需要实现各个服务之间的通信。

通信如何实现,主要有两种方式:

(1)使用专业的RPC框架:如Dubbo等;
(2)自己手写RPC实现微服务之间的通信。

实现了微服务通信后,就要面临这个用户请求的负债均衡,这个就需要用到Spring Cloud Netflix Ribbon,这个就是本文的主角。

新建两个工程

好了,新建的时候注意两点:
(1)使用阿里镜像而不是spring官网;
(2)选择Spring Web/Web。



运行结果(使用restTemplate封装的http调用成功):

三、Ribbon负载均衡的使用

3.1 Ribbon负载均衡的原理

上面是一个order订单服务,一个user消费者,但是如果服务端(order)启动多个订单服务,客户端(user)需要使用Ribbon作负载均衡,Ribbon默认使用轮询的方式实现负载均衡。

Ribbon是客户端负载原理,如下图所示:

注意两点:
(1)Ribbon是客户端负载不是服务端负载;
(2)Ribbon有多中负载均衡方式,默认是轮询方式。

3.2 Ribbon负载均衡的实现

第一步,user工程(即客户端/使用端)导入ribbon依赖:


第二步,order工程(服务端/提供端)提供两种接口服务:

第三步,user工程(客户端/使用端)在application.properties文件中配置order服务的地址列表:

第四,user工程中主代码中加上负载均衡

对于RestTemplate,ioc容器中,一开始没有这个类实例,所有需要@Bean创建一个才能用@Autowired取出;
对于LoadBalancerClient,ioc容器中,一开始就有这个类实例,所有直接用@Autowired取出。

第五步,order工程中,打印一下客户端当前请求到的服务:

运行结果:

因为默认是轮询机制,所以是轮询了。

区别:Nginx负载均衡和Ribbon负载均衡的关系
回答:没有任何关系,Nginx是整个后端架构的网关层的负载均衡,Ribbon是微服务架构中(单体架构没有)服务调用方对于服务消费的负载均衡。

附加,也可以直接使用注解@LoadBalanced的方式

四、Ribbon源码解析

4.1 初始化三个bean,拦截所有带有@LoadBalance注解的RestTemplate

4.1.1 拦截器的引入

我们再来看一次Ribbon原理图,如果放在user工程中的ribbon组件,要起到负载均衡的作用,需要有一个拦截器,可以拦截restTemplate的请求,拦截之后,再解析出ip地址。


对于这个图的解释:当浏览器访问localhost:8088调用user工程的时候,user工程中ribbon组件可以对加了@LoadBalancer注解的所有restTemplate,就是拦截,使用的拦截器就是LoadBalancerIntercepter类,拦截之后再解析出ip地址,访问http://ip:port。

4.1.2 @Qualifier注解

拦截是怎样实现的,是如何识别所有加了@LoadBalancer注解的RestTemplate的,先来认识一下@Qualifier注解。

新建一个TestClass类

写一个测试Configuration类和一个测试Controller类:

这里注意,要修改一下SpringCloudUserServiceApplication类,让它扫描到Controller类注解:

运行结果:

小结:
所以,@Qualifier注解的作用就是:
(1)用于标注一些bean;(2)用于取出被@Qualifier标注的那些bean。

我们知道,在user工程中,restTemplate被@LoadBalanced注解修饰,如下:


让我们再来拿来看一下@LoadBalanced注解的定义,点进去,如下:

@LoadBalanced注解是一个被@Qualifier修饰的注解,所有RestTemplate这个bean也是被@Qualifier修饰的,那么springioc容器中,就可以通过查找被@Qualifier修饰的bean,精准的定位到restTemplate这个bean了,事实也确实是这样。

4.1.3 初始化三个bean,拦截所有带有@LoadBalance注解的RestTemplate

我们刚才上面的代码,使用过两种方式实现负载均衡,分别是直接注入一个LoadBalancerClient,和在RestTemplate上加上 @LoadBalanced 注解。


对于两种方式,底层走的代码路劲是不同的。

对于@LoadBalanced注解,这个注解被@Qualifier修饰,在LoadBalancerAutoConfiguration类中通过定位被@Qualifier修饰的类,来定位被@LoadBalanced修改的bean,放到一个名为restTemplates的list中。然后经过三个bean的处理,从前到后分别是:LoadBalancerInterceptor、RestTemplateCustomizer、SmartInitializingSingleton。


这三个bean的执行顺序是一定不会改变,因为第二个bean的定义需要springioc容器中存在第一个bean的实例,作为实参传递过来;第三个bean的定义需要springioc容器中存在第二个bean的实例,作为实参传递过来。

所以,对于@LoadBalanced注解,通过三个bean的定义,设置好了拦截器。

对于LoadBalancerClient,这个LoadBalancerClient的实现类是什么?答案是RibbonLoadBalancerClient,为什么?请看代码

附加:两种方式/两个配置类的联系

一图小结:两种方式/两种配置类

4.2 获得所有拦截住的LoadBalancer,再根据LoadBalancer获得到具体的Server,实现负载均衡

4.2.1 进入拦截器中

在上面我们知道,对于主代码中

restTemplate.getForObject("http://spring-cloud-order-service/orders", String.class);

一定会被拦截器拦截,进入到拦截器方法中,如下 LoadBalancerinterceptor.intercept()

进入到LoadBalancerClient.execute()方法,这是一个接口,其具体实现是 RibbonLoadBalancerClient.execute(),如下:

4.2.2 根据serviceId得到具体的负载均衡器

核心代码:IBalance=getLoadBalancer(serviceId)

现在我们来分析这一句 IBalance=getLoadBalancer(serviceId),根据serviceId得到负载均衡器,



这里注意:应该是进入到NameContextFactory的getInstance()方法,因为当前就是在SpringClientFactory类中。


这里,debug启动断点getInstance()这个地方,可以知道,最后得到的是一个ZoneAwareLoadBalancer对象,它是IBalancer接口的是一个实现类。

4.2.3 根据负载均衡器得到具体的服务器

核心代码:getServer(loadBalancer,hint)

回到RibbonLoadBalancerClient类的execute()方法,完成了getLoadBalancer(serviceId),现在是 getServer(loadBalancer, hint);



这个key就是负载均衡算法,默认是轮询。

继续点进去,如下:

附加:其实可以看看IRule接口的其他实现,即其他的负载均衡算法,如下:


比如,常见的随机算法:

4.2.4 生成RibbonServer并执行

到现在,执行完了getLoadBalancer()和getServer(),得到一个server,就生成RibbonServer,并执行,完成了。

最后小结一下这个部分(拦截器拦截+根据serviceId得到ZoneAwareLoadBalancer负载均衡器+根据负载均衡器balancer和负载均衡算法rule得到服务器节点server),如下图:

五、尾声

看顶级渣男如何邀约100个女朋友(一),完成了。

天天打码,天天进步!

看顶级渣男如何邀约100个女朋友(一)相关推荐

  1. 看顶级渣男如何邀约100个女朋友(二)

    文章目录 一.前言 二.从getForObject()是如何进入LoadBalanceInterceptor.intercept()方法的 三.获得服务列表,间隔更新服务列表,将服务列表存储在内存变量 ...

  2. 含泪控诉人类科技史上的三个顶级“渣男”!

    ‍数据智能产业创新服务媒体 --聚焦数智 · 改变商业 在最近一百年的人类科技史上,有三个顶级"渣男"--人工智能.元宇宙.可控核聚变.说他们"渣",并没有冤枉 ...

  3. 【干货+福利】情侣、基友、渣男和狗-基于SynchroTrap+LPA算法的团伙账户挖掘

    本文目的:把经常一起行动的人找出来,并划分成一个Group,仅利用时间关系,无需其他介质 上一期的文章,没有解决相隔时间近但是不在同一个5min切片内的的问题,为了解决这个问题,我研究了一些关于时序的 ...

  4. 哈工大导师禁止实验室硕士出去实习,称「实习就像和35岁渣男试婚」,你怎么看?...

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文授权转载自募格学术(ID:mugexueshu) 参考资料:知乎 ...

  5. MySQL从删库到跑路(7):连接查询,用联系的观点看女神与渣男

     "有为,能陪我说说话么?"  望着梨花带雨的女神,一时间李有为陷入了恍惚之中,尽管心里已经千万次告诫自己要远离面前的女人,可是当她真的出现在面前时,李有为的大脑早已一片空白.   ...

  6. 二手房销售员邀约客户看房有哪些话术和销售技巧

    房地产销售邀约客户看房有哪些销售话术?看房前.看房中分别使用什么样的销售话术更加合适?下面分享一些. 二手房销售带客户看房前: 1.再一次确认时间地点,约客户时间点,约房东时间段(在20分钟左右),防 ...

  7. 看渣男经常会说哪些话,渣男的评判标准

    60.对不起,我还爱你. 61.她主动勾引我,我对她一点感觉都没有. 62.先打孩子,我保证以后会娶你. 63.宝贝没什么好的. 64.乖,我们不买. 65.你为什么又生气了?我错了,好吗? 66.别 ...

  8. tiktok达人邀约重点看哪些数据?小白求答!

    我们大家都知道通过达人带货,可以在短时间内实现爆单,可以在短时间内快速获得订单.但要想达人带货效果更好,则取决于我们自己选择的达人哦!不小小白在问,tiktok达人邀约重点看哪些数据?有大神解答吗? ...

  9. 「码个蛋」邀约投稿,收获个人成长

    分享即是一件能够让自己成长又是能帮助他人的事情. 码个蛋支持投稿了,让我们一起分享,共同成长,分享使我们并不孤独. 投稿「不仅可以使得你的文章和你的博客传播力更广,而且文章赞赏的全部收入归你所有,除此 ...

最新文章

  1. leveldb源码分析:数据插入续(跳表)
  2. 30幅非常漂亮的微距摄影作品欣赏
  3. spring中lazy-init详解
  4. Oracle数据库安装图文操作步骤
  5. Mysql5.6.23免安装配置
  6. ES6、7学习笔记(尚硅谷)-3-变量的解构赋值
  7. Windows XP英文版安装中文语言包来解决无法显示中文的方法
  8. tushare平台介绍
  9. 3d max2012安装 破解注册机需要注意的地方
  10. python复数类型的虚部通过什么表示_Python小白必备知识:Python复数类型(complex)详解...
  11. Unity 复制内容到剪贴板
  12. 在VC6.0下设置Unicode编译环境
  13. IndexedDB 包装库 idb
  14. 【转自Testerhome】iOS 真机如何安装 WebDriverAgent
  15. 你的私密照片可能正被“合法”观看
  16. 深度学习必备三种基本绘图技能
  17. 对越Altium Designer 17.0.9电路设计软件
  18. 什么是智能工厂,印刷企业如何实现智能化
  19. 1222222222
  20. 25k~50k,比特大陆招人啦!这次会是你吗?

热门文章

  1. apache-maven-3.8.5配置
  2. 【Linux | 系统编程】Linux系统编程(文件、进程线程、进程间通信)
  3. numpy 轴与维度的理解
  4. 2020-09-02
  5. 宇视网络视频录像机如何修改宇视摄像机网络地址
  6. 列的完整性约束——设置表字段值自动增加(AUTO_INCREMENT)
  7. 石墨笔记,为知笔记和Effie哪个更适合学生?
  8. redis的基本操作And数据持久化方式以及redis实现mybatis缓存
  9. pc模式 华为mate30_华为Mate30系列10个隐藏黑科技
  10. (干货)全面分析6大国产CPU处理器