当前位置:网站首页>【云原生&微服务八】Ribbon负载均衡策略之WeightedResponseTimeRule源码剖析(响应时间加权)
【云原生&微服务八】Ribbon负载均衡策略之WeightedResponseTimeRule源码剖析(响应时间加权)
2022-06-23 11:31:00 【秃秃爱健身】
一、前言
前置Ribbon相关文章:
- 【云原生&微服务一】SpringCloud之Ribbon实现负载均衡详细案例(集成Eureka、Ribbon)
- 【云原生&微服务二】SpringCloud之Ribbon自定义负载均衡策略(含Ribbon核心API)
- 【云原生&微服务三】SpringCloud之Ribbon是这样实现负载均衡的(源码剖析@LoadBalanced原理)
- 【云原生&微服务四】SpringCloud之Ribbon和Erueka集成的细节全在这了(源码剖析)
- 【微服务五】Ribbon随机负载均衡算法如何实现的
- 【微服务六】Ribbon负载均衡策略之轮询(RoundRobinRule)、重试(RetryRule)
- 【微服务七】Ribbon负载均衡策略之BestAvailableRule
我们聊了以下问题:
- 为什么给RestTemplate类上加上了@LoadBalanced注解就可以使用Ribbon的负载均衡?
- SpringCloud是如何集成Ribbon的?
- Ribbon如何作用到RestTemplate上的?
- 如何获取到Ribbon的ILoadBalancer?
- ZoneAwareLoadBalancer(属于ribbon)如何与eureka整合,通过eureka client获取到对应注册表?
- ZoneAwareLoadBalancer如何持续从Eureka中获取最新的注册表信息?
- 如何根据负载均衡器
ILoadBalancer从Eureka Client获取到的List<Server>中选出一个Server?- Ribbon如何发送网络HTTP请求?
- Ribbon如何用IPing机制动态检查服务实例是否存活?
- Ribbon负载均衡策略之随机(
RandomRule)、轮询(RoundRobinRule)、重试(RetryRule)、选择并发量最小的(BestAvailableRule)实现方式;
本文继续讨论 根据响应时间加权算法(WeightedResponseTimeRule)是如何实现的?
二、WeightedResponseTimeRule
WeightedResponseTimeRule继承自RoundRobinRule,也就是说该策略是对RoundRobinRule的扩展,其增加了 根据实例运行情况来计算权重 并根据权重挑选实例的规则,以达到更优的负载、实例分配效果。
下面我们一点点来看WeightedResponseTimeRule是如何实现根据相应时间计算权重并根据权重挑选实例的?
1、计算权重?
WeightedResponseTimeRule在初始化的时候会初始化父类RoundRobinRule,在RoundRobinRule的有参构造函数中会调用setLoadBalancer(ILoadBalancer)方法,WeightedResponseTimeRule类中重写了setLoadBalancer(ILoadBalancer)方法,在setLoadBalancer(ILoadBalancer)中会调用initialize(ILoadBalancer)对权重进行初始化、并定时更新。
public static final int DEFAULT_TIMER_INTERVAL = 30 * 1000;
private int serverWeightTaskTimerInterval = DEFAULT_TIMER_INTERVAL;
1)如何更新权重?
WeightedResponseTimeRule通过Timer#schedule()方法启动一个上一个任务结束到下一个任务开始之间间隔30s执行一次的定时任务为每个服务实例计算权重;
定时任务的主体是DynamicServerWeightTask:
// WeightedResponseTimeRule的内部类
class DynamicServerWeightTask extends TimerTask {
public void run() {
ServerWeight serverWeight = new ServerWeight();
try {
serverWeight.maintainWeights();
} catch (Exception e) {
logger.error("Error running DynamicServerWeightTask for {}", name, e);
}
}
}
DynamicServerWeightTask的run()方法中会实例化一个ServerWeight对象,并通过其maintainWeights()方法计算权重。
2)如何计算权重?
无论是权重的初始化还是权重的定时更新,都是使用ServerWeight#maintainWeights()方法来计算权重:
// WeightedResponseTimeRule的内部类
class ServerWeight {
public void maintainWeights() {
ILoadBalancer lb = getLoadBalancer();
if (lb == null) {
return;
}
// CAS保证只有一个线程可以进行权重的计算操作
if (!serverWeightAssignmentInProgress.compareAndSet(false, true)) {
return;
}
try {
logger.info("Weight adjusting job started");
AbstractLoadBalancer nlb = (AbstractLoadBalancer) lb;
LoadBalancerStats stats = nlb.getLoadBalancerStats();
if (stats == null) {
return;
}
// 所有实例的平均响应时间总和
double totalResponseTime = 0;
for (Server server : nlb.getAllServers()) {
// 汇总每个实例的平均响应时间到totalResponseTime上
ServerStats ss = stats.getSingleServerStat(server);
totalResponseTime += ss.getResponseTimeAvg();
}
// 计算每个实例的权重:weightSoFar + totalResponseTime - 实例的平均响应时间
// 实例的平均响应时间越长、权重就越小,就越不容易被选择到
Double weightSoFar = 0.0;
List<Double> finalWeights = new ArrayList<Double>();
for (Server server : nlb.getAllServers()) {
ServerStats ss = stats.getSingleServerStat(server);
double weight = totalResponseTime - ss.getResponseTimeAvg();
weightSoFar += weight;
finalWeights.add(weightSoFar);
}
setWeights(finalWeights);
} catch (Exception e) {
logger.error("Error calculating server weights", e);
} finally {
// 表示权重计算结束,允许其他线程进行权重计算
serverWeightAssignmentInProgress.set(false);
}
}
}
方法的核心逻辑:
- LoadBalancerStats中记录了每个实例的统计信息,累加所有实例的平均响应时间,得到总平均响应时间
totalResponseTime;- 为负载均衡器中维护的实例列表逐个计算权重(从第一个开始),计算规则为:weightSoFar + totalResponseTime - 实例的平均响应时间;
- 其中
weightSoFar初始化为零,并且每计算好一个权重需要累加到weightSoFar上供下一次计算使用;
3)例证权重的计算
举个例子,假如服务A有四个实例:A、B、C、D,他们的平均响应时间(单位:ms)为:10、50、100、200。
- 服务A的所有实例的总响应时间(
totalResponseTime)为:10 + 50 + 100 + 200 = 360;- 每个实例的权重计算规则为:
总响应时间(totalResponseTime)减去实例的平均响应时间+累加的权重weightSoFar,具体到每个实例的计算如下:
- 实例A:
230 - 10 + 0 = 220(weightSoFar = 0)- 实例B:
230 - 50 + 220 = 400(weightSoFar = 220)- 实例C:
230 - 100 + 400 = 530(weightSoFar = 400)- 实例D:
230 - 200 + 530 = 560(weightSoFar = 530)
这里的权重值表示各实例权重区间的上限,以上面的计算结果为例,它为这4个实例各构建了一个区间:
- 每个实例的区间下限是上一个实例的区间上限;
- 每个实例的区间上限是我们计算出的并存储于在
List<Double>类型的accumulatedWeights变量中的权重值,其中第一个实例的下限默认为零。
所以,根据上面示例的权重计算结果,我们可以得到每个实例的权重区间:
- 实例A:
[0,220](weightSoFar = 0)- 实例B:
(220, 400](weightSoFar = 220)- 实例C:
(400, 530](weightSoFar = 400)- 实例D:
(530, 560](weightSoFar = 530)
从这里我们可以确定每个区间的宽度实际就是:总的平均响应时间 - 实例的平均响应时间,所以服务实例的平均响应时间越短、权重区间的宽度就越大,服务实例被选中的概率就越高。
这些区间边界的开闭如何确定?区间在哪里使用?
2、权重的使用
我们知道Ribbon负载均衡算法体现在IRule的choose(Object key)方法中,而choose(Object key)方法中又会调用choose(ILoadBalancer lb, Object key)方法,所以我们只需要看WeightedResponseTimeRule的choose(ILoadBalancer lb, Object key)方法:
方法的核心流程如下:
- 如果服务实例的最大权重值 < 0.001 或者服务的实例个数发生变更,则采用父类
RoundRobinRule做轮询负载;- 否则,利用Random函数生成一个随机数randomWeight,然后遍历权重列表,找到第一个权重值大于等于随机数randomWeight的列表索引下标,然后拿当前权重列表的索引值去服务实例列表中获取具体实例。
1)权重区间问题?
正常每个区间都为(x, y],但是第一个实例和最后一个实例不同:
- 由于随机数的最小取值可以为0,所以第一个实例的下限是闭区间;
- 随机数的最大值取不到最大权重值,所以最后一个实例的上限是开区间;
边栏推荐
- [cloud based co creation] overview of the IOT of Huawei cloud HCIA IOT v2.5 training series
- Over a year, time has changed. Chinese chips have made breakthroughs, but American chips are difficult to sell
- 惊!AMD 350亿美元收购赛灵思!
- Daily question 7-1652 Defuse the bomb
- How does easygbs solve the abnormal use of intercom function?
- 【进程和线程】
- “芯”有灵“蜥”,万人在线!龙蜥社区走进 Intel MeetUp 精彩回顾
- What are the top ten securities companies in China? Is it safe to open a mobile account?
- 一张图解码 OpenCloudOS 社区开放日
- 浅谈标注平台架构
猜你喜欢

mysql,如何在使用存储过程计算最大值

64路电话+2路千兆以太网64路PCM电话光端机语音电话转光纤

The simplest DIY pca9685 steering gear control program based on the integration of upper and lower computers of C # and 51 single chip microcomputer

Design and implementation of stm32f103zet6 single chip microcomputer dual serial port mutual sending program

【进程和线程】

php 手写一个完美的守护进程

直播带货app源码搭建中,直播CDN的原理是什么?

汉源高科USB2.0光端机USB2.0光纤延长器USB2.0光纤传输器USB2.0接口转光纤

4E1 PDH光端机19英寸机架式单纤传输20km E1接口光纤网络光端机

汉源高科USB3.0光端机USB工业触摸屏光端机USB3.0光纤延长器USB3.0光纤传输器
随机推荐
Vone news | wanglian technology empowers the public to enjoy the self-organization management of the chain network, creating an enterprise level alliance Dao
Gary Marcus发文:AI研究者需要知道的三个来自语言学家的观点
Design and implementation of esp32-cam wireless monitoring intelligent gateway
一般的理财产品期限是几天啊?
使用tensorflow2创建神经网络
Whether Changan Lumin has the ability to become a broken product in the micro electricity market
Android security / reverse interview questions
tensorflow2的GradientTape求梯度
运行时应用自我保护(RASP):应用安全的自我修养
浅谈标注平台架构
六张图详解LinkedList 源码解析
OpenHarmony应用开发【01】
全国进入主汛期,交通运输部:不具备安全运行条件的线路坚决停运!
Google Earth Engine(GEE)——GEDI L2A Vector Canopy Top Height (Ver
Vone新闻 | 旺链科技赋能众享链网自组织管理,打造企业级联盟DAO
Not satisfied with the effect of the smart park? Please accept this secret script of thingjs
Win10 微软输入法(微软拼音) 不显示 选字栏(无法选字) 解决方法
你真的理解LDO的輸出電容嗎!?
【ML】QuantileRegressor
Tensorrt notes (4) Modèle de segmentation du raisonnement