0
点赞
收藏
分享

微信扫一扫

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



文章目录


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

  • ​​3.1 过渡,从LoadBalanceInterceptor.intercept()出发...​​
  • ​​3.2 获得服务列表,间隔更新服务列表​​

  • ​​3.2.1 restOfInit()方法​​
  • ​​3.2.2 enableAndInitLearnNewServersFeature()方法​​

  • ​​3.3 将服务列表存储在内存变量中​​
  • ​​3.4 心跳机制(ping测试服务列表中的服务是否存活)​​

  • ​​四、IRule接口之源码中各种各样的负载均衡策略​​

  • ​​4.1 简单负载均衡策略​​
  • ​​4.2 权重负载均衡策略(根据后端的响应时间合理规划负载均衡的权重)​​
  • ​​4.3 自己动手实现一种负载均衡算法​​

  • ​​五、尾声​​


一、前言

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

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

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

二、从getForObject()是如何进入LoadBalanceInterceptor.intercept()方法的

看顶级渣男如何邀约100个女朋友(二)_权重

看顶级渣男如何邀约100个女朋友(二)_权重_02

看顶级渣男如何邀约100个女朋友(二)_服务列表_03

看顶级渣男如何邀约100个女朋友(二)_负载均衡_04

先看 ​​ClientHttpRequest request = createRequest(url, method);​​ 点进去,到了HttpAccessor类中,

看顶级渣男如何邀约100个女朋友(二)_权重_05

看顶级渣男如何邀约100个女朋友(二)_服务列表_06

看顶级渣男如何邀约100个女朋友(二)_服务列表_07

好了,我们先看getInterceptors()方法是如何得到拦截器的

看顶级渣男如何邀约100个女朋友(二)_负载均衡_08

看顶级渣男如何邀约100个女朋友(二)_权重_09

其实,上一篇博客,早在LoadBalancerAutoConfiguration类中,讲解三个bean的初始化的时候,我们就看到interceptors的赋值,这里来看一下,它就在:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_10

好了,getInterceptor()方法得到拦截器之后,新建一个了InterceptingClientHttpRequestFactory工厂并返回,这样InterceptingHttpAccessor类就看完了,我们回到调用方HttpAccessor类的createRequest()方法,

看顶级渣男如何邀约100个女朋友(二)_负载均衡_11

看顶级渣男如何邀约100个女朋友(二)_服务列表_12

附加一句:

看顶级渣男如何邀约100个女朋友(二)_服务列表_13

看顶级渣男如何邀约100个女朋友(二)_服务列表_14

看顶级渣男如何邀约100个女朋友(二)_服务列表_15

看顶级渣男如何邀约100个女朋友(二)_权重_16

好了,看完了,现在返回HttpAccessor类的createRequest方法,如下:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_17

回到RestTemplate类的doExecute()方法,如下:

看顶级渣男如何邀约100个女朋友(二)_权重_18

看顶级渣男如何邀约100个女朋友(二)_权重_19

看顶级渣男如何邀约100个女朋友(二)_权重_20

看顶级渣男如何邀约100个女朋友(二)_负载均衡_21

看顶级渣男如何邀约100个女朋友(二)_服务列表_22

看顶级渣男如何邀约100个女朋友(二)_负载均衡_23

看顶级渣男如何邀约100个女朋友(二)_负载均衡_24

看顶级渣男如何邀约100个女朋友(二)_服务列表_25

看顶级渣男如何邀约100个女朋友(二)_负载均衡_26

所以,不断执行后,最后返回给RestTemplate类的doExecute()方法,如下:

看顶级渣男如何邀约100个女朋友(二)_服务列表_27

三、获得服务列表,间隔更新服务列表,将服务列表存储在内存变量中

3.1 过渡,从LoadBalanceInterceptor.intercept()出发…

对于LoadBalanceInterceptor类的intercept()方法,执行了loadbalancer.execute()方法,参数一共四个,分别是服务名serviceName,实参request,实参body,实参execution,如下图:

看顶级渣男如何邀约100个女朋友(二)_权重_28

点进去,就从LoadBalancerInterceptor类导流RibbonLoadBalancerClient类,这里有三个execute()方法,如下图:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_29

其中,第二个,就是两个参数的execute()方法,就是上一篇博客介绍过的,先获得负载均衡器,然后获得服务节点,我们再次跟到服务节点中去:

看顶级渣男如何邀约100个女朋友(二)_服务列表_30

看顶级渣男如何邀约100个女朋友(二)_权重_31

看顶级渣男如何邀约100个女朋友(二)_负载均衡_32

看起来,ZoneAwareLoadBalancer类中的chooseServer()方法的逻辑完成了,但是这里补充一句,chooseServer()方法中如果满足 ​​getLoadBalancerStats().getAvailableZones().size() <= 1​​​ 或者最后执行 ​​zoneLoadBalancer.chooseServer(key);​​ 得到的server为null,就是执行父类的chooseServer()方法,就是BaseLoadBalancer类的chooseServer()方法。

看顶级渣男如何邀约100个女朋友(二)_权重_33

看顶级渣男如何邀约100个女朋友(二)_负载均衡_34

规则默认是轮询,可以设置

看顶级渣男如何邀约100个女朋友(二)_负载均衡_35

3.2 获得服务列表,间隔更新服务列表

3.2.1 restOfInit()方法

我们看到,在ZoneAwareLoadBalancer的父类,DynamicServerListLoadBalancer的构造方法中,调用过一个名为restOfInit()的方法,如下:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_36

看名称像是一个初始化方法,而且还在构造函数中被调用,应该是一个启动设置相关的方法,那么到底设置什么呢?其实,就是获取application.properties本地配置文件中配置中的地址列表,并把它设置到程序中的两个list中。

进入restOfInit()方法看看具体逻辑吧,如下:

看顶级渣男如何邀约100个女朋友(二)_服务列表_37

3.2.2 enableAndInitLearnNewServersFeature()方法

先看​​enableAndInitLearnNewServersFeature()​​方法,如下:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_38

这里包含两个东西,一个是start()方法,一个是updateAction,我们先看看这个start()方法,点进去,如下:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_39


问题:任务启动以后延期1秒执行,每次刷新的间隔时间是30秒的源码依据在哪里?
回答:看顶级渣男如何邀约100个女朋友(二)_负载均衡_40
问题2:第二个构造函数,那个getRefreshIntervalMs(clientConfig)方法,点进去看一下呗?
回答2:看顶级渣男如何邀约100个女朋友(二)_服务列表_41
看顶级渣男如何邀约100个女朋友(二)_负载均衡_42


我们看到,start()方法中在按照“任务启动以后延期1秒执行,每次刷新的间隔时间是30秒”执行着任务,执行的这个任务是什么?就是start()方法传入的实参——updateAction,看一看这个updateAction:

看顶级渣男如何邀约100个女朋友(二)_权重_43

所以,这个updateAction就是定时更新服务地址列表,进入updateListOfServers()方法,如下:

看顶级渣男如何邀约100个女朋友(二)_服务列表_44

这里调用了一个​​serverListImpl.getUpdatedListOfServers()​​才能获得servers,看来秘密就在这里面,点进去看一看,

看顶级渣男如何邀约100个女朋友(二)_负载均衡_45

这个key值是什么?点进去看看

看顶级渣男如何邀约100个女朋友(二)_权重_46

回到ConfigurationBasedServerList类的getUpdatedListOfServers()方法,原来这个方法就是将配置文件中的地址列表出来。所以,调用方DynamicServerListLoadBalancer类中的updateListOfServers()方法中就是得到了本地配置文件中的地址列表存放到servers变量中。

看顶级渣男如何邀约100个女朋友(二)_服务列表_47


其实,获取地址列表有两种,一是本地配置文件中的地址列表,还有一种是Eureka注册中心的地址列表,因为没有导入eureka依赖,所以​​serverListImpl.getUpdatedListOfServers()​​这里ctrl+alt+左键没有弹出来,所以略去。


3.3 将服务列表存储在内存变量中

在BaseLoadBalancer类中,有两个list类型的类变量allServerLIst和upServerList,这两个list是服务端地址列表在客户端内存中的存储,如下:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_48

那么我们的问题,这两个list在哪里被初始化,在哪里被更新?这是本节的问题。

上面,在DynamicServerListLoadBalancer类中的updateListOfServers()方法,最后一句调用了updateAllServerList()方法,点进去看看:

看顶级渣男如何邀约100个女朋友(二)_服务列表_49

再进入setServersList()方法,如下:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_50

点击super.setServersList()方法,进入BaseLoadBalancer类中的setServersList()方法,如下:看顶级渣男如何邀约100个女朋友(二)_权重_51

看顶级渣男如何邀约100个女朋友(二)_负载均衡_52

好了,返回回去看一看吧!

看顶级渣男如何邀约100个女朋友(二)_服务列表_53

看顶级渣男如何邀约100个女朋友(二)_负载均衡_54

至此,这个restOfInit()方法完成了“获得服务列表,间隔更新服务列表,将服务列表存储在内存变量中”。

3.4 心跳机制(ping测试服务列表中的服务是否存活)

Ribbon有一种类似心跳的ping机制,如果服务列表中的服务宕机了,即注册中心(Eureka)不通知,Ribbon也可以知道,当服务列表中某一个服务宕机后,Ribbon可以用自己的ping机制知道,将无法访问的节点剔除掉,从而改变内存中两个list的存储,这有点向Eureka服务注册中应该实现的东西。那么,源码中是怎么实现的呢?一起来看看吧。

找到BaseLoadBalancer类中的setupPingTask()方法,

看顶级渣男如何邀约100个女朋友(二)_负载均衡_55

点进去new PingTask(),看一看这个PingTask类的具体任务:

看顶级渣男如何邀约100个女朋友(二)_服务列表_56

在代码行 ​​new Pinger(pingStrategy).runPinger()​​ 中,来看看runPinger()方法的具体逻辑,

看顶级渣男如何邀约100个女朋友(二)_服务列表_57

看顶级渣男如何邀约100个女朋友(二)_权重_58

看顶级渣男如何邀约100个女朋友(二)_权重_59

其实,IPing有不同的实现,比如PingUrl类,如下:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_60

isAlive()也很容易就看懂了

看顶级渣男如何邀约100个女朋友(二)_负载均衡_61

我们现在搞清楚了Ribbon的心跳机制和两个list区别,我们再看看这个ping是在哪里定义的?ping是怎么和loadBalancer联系的(即心跳机制怎么帮助负载均衡)?

看顶级渣男如何邀约100个女朋友(二)_服务列表_62

看顶级渣男如何邀约100个女朋友(二)_负载均衡_63

好了,那么第二个问题,ping是怎么和loadBalancer联系的(即心跳机制怎么帮助负载均衡)?回到RibbonClientConfiguration类,如下:

看顶级渣男如何邀约100个女朋友(二)_权重_64

四、IRule接口之源码中各种各样的负载均衡策略

4.1 简单负载均衡策略

找到IRule接口,

看顶级渣男如何邀约100个女朋友(二)_服务列表_65

我们先来看看比较简单的轮询负载均衡、随机负载均衡、重试负载均衡。

轮询负载均衡策略

看顶级渣男如何邀约100个女朋友(二)_权重_66

看顶级渣男如何邀约100个女朋友(二)_服务列表_67

随机负载均衡策略

看顶级渣男如何邀约100个女朋友(二)_权重_68

看顶级渣男如何邀约100个女朋友(二)_负载均衡_69

重试负载均衡策略

看顶级渣男如何邀约100个女朋友(二)_权重_70

小结:无论是轮询、随机、重试,这些负载均衡策略虽然简单,但是很难真正起到负载均衡的作用,要想真正起到负载均衡的作用,要需要更好的负载均衡规则rule,且看下面的权重负载均衡策略,根据后端的响应时间合理规划负载均衡的权重。

4.2 权重负载均衡策略(根据后端的响应时间合理规划负载均衡的权重)

找到WeightedResponseTimeRule类,这个权重类是轮询类的子类,所以这个权重算法以轮询为基础的,它的本质是在轮询的基础上对各个服务节点加上权重,从而使自己轮询的时候的比重更多。

看顶级渣男如何邀约100个女朋友(二)_权重_71

看顶级渣男如何邀约100个女朋友(二)_服务列表_72

对于核心代码的解释

代码如下:

double randomWeight = random.nextDouble() * maxTotalWeight;
// pick the server index based on the randomIndex
int n = 0;
for (Double d : 140>=) {
if (d >= randomWeight) {
serverIndex = n;
break;
} else {
n++;
}
}

server = allList.get(serverIndex);

解释:比如,服务节点A的响应时间是10毫秒,服务节点B的响应时间是20毫秒,服务节点C的响应时间是40毫秒,三种服务节点中,A的响应时间最快,C的响应时间最慢。

如果要求每一个服务节点,总的时间时间为150毫秒

A=[0,(150-10)]=[0,140]

B=(140,140+(150-20)]=(140,270]

C=(270,270+(150-40)]=(270,380]

区间表示这个权重,然后随机生成一个数字,看这个数字落在哪个服务节点负责的区间,就选择哪个服务节点。

如果是randomWeight是40,那么开始循环遍历 ​​for (Double d : currentWeights)​​ 这三个节点,对于A节点,满足 140>=40 ,所以执行 ​​serverIndex = n;​​ 然后break,最后执行 ​​server = allList.get(serverIndex);​

选出A节点;

如果是randomWeight是240,那么开始循环遍历 ​​for (Double d : currentWeights)​​​ 这三个节点,对于A节点,不满足 ​​if (d >= randomWeight)​​​,走else分支,​​n++​​​ 操作之后 n为1,对于B节点,满足 270>240,所以执行 ​​serverIndex = n;​​​ 然后break,最后执行 ​​server = allList.get(serverIndex);​​选出B节点;

如果是randomWeight是340,那么开始循环遍历 ​​for (Double d : currentWeights)​​​ 这三个节点,对于A节点和B节点,都不满足 ​​if (d >= randomWeight)​​​,走else分支,两次 ​​n++​​​ 操作之后 n为1,对于C节点,满足 380>240,所以执行 ​​serverIndex = n;​​​ 然后break,最后执行 ​​server = allList.get(serverIndex);​​选出C节点;

4.3 自己动手实现一种负载均衡算法

自己动手实现一种负载均衡算法不是很难,我们可以实现一个自己的负载均衡算法,如下:

看顶级渣男如何邀约100个女朋友(二)_负载均衡_73

五、尾声

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

天天打码,天天进步!!



举报

相关推荐

如何看一个报错异常

0 条评论