githubEdit

2. ThresholdShedder + LeastResourceUsageWithWeight

2.1 环境配置

搭建一个5节点的broker集群,包含30个bookie。

负载均衡相关配置如下:

loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.impl.ThresholdShedder
loadBalancerLoadPlacementStrategy=org.apache.pulsar.broker.loadbalance.impl.LeastResourceUsageWithWeight

使用ThresholdShedder + LeastResourceUsageWithWeight的组合,配置基本都使用默认值,但是同样关闭了bundle split、bundle均匀分布的特性。

loadBalancerDistributeBundlesEvenlyEnabled=false
loadBalancerAutoBundleSplitEnabled=false
loadBalancerAutoUnloadSplitBundlesEnabled=false

2.2 过度加载问题

启动三个压测任务:

启动压测任务后,集群花费了22min才稳定了下来,触发了8次bundle unload。

为了方便debug,添加了部分日志。第一次触发bundle unload时的日志如下:

这行日志打印了所有broker的中间分数(即当前所有broker的最大资源使用率,未使用历史均值打分算法),可以看到当前XXX.83:8081、XXX.32:8081、XXX.206:8081是高载broker,另外两个broker是低载的。

这行日志打印了所有broker的最终得分(即使用了历史均值打分算法)、平均分、阈值。

从前面两行日志可知,在启动压测任务前,各个 broker 负载均处于较低水平,启动压测任务后负载突增,此时所有 broker 的得分与真实负载存在较大偏差。其中,仅 XXX.206:8081 的得分超过了阈值,即 28.95% > 17.35% + 10.0% 。于是对其执行 bundle unload 操作,得到如下日志:

卸载一个bundle,并立刻执行放置策略LeastResourceUsageWithWeight:

由于任意一个 broker 的分数加上 10 均大于 10.7% 的平均分,故而候选 broker 列表为空,进而触发随机分配机制。这正是我们之前所阐述的 LeastResourceUsageWithWeight 问题:候选 broker 列表极易为空,最终导致随机分配情况的出现。

可以看到,卸载下来的bundle分配到了高载的XXX.83:8081!这是一次失败的负载均衡决策。

在本次实验中,该问题的触发概率极高,近乎必然出现。从下图可以清晰看到,问题已连续四次触发。

复现概率之所以如此之高,历史均值打分算法也要背锅。这是因为候选 broker 的挑选条件为:broker 打分需比平均分低 10 分,这意味着 broker 之间的分数要拉开较大差距。然而,由于历史均值打分算法的影响,所有 broker 的分数仅能从 20 左右逐渐逼近其真实负载,致使不同 broker 之间的分数长期难以拉开差距,如此一来,LeastResourceUsageWithWeight 算法便只能进行随机分配了 。

2.3 过度卸载问题

为了增加单台broker的负载,缩容两台broker,观察到一次异常的负载均衡。

可以看到,黄色机器在高负载与低负载状态间频繁切换。其 CPU 使用率从 80% 降至 40%,随后又从 40% 回升至 80%。在此过程中,先是引发了过度卸载问题,紧接着又触发了过度加载问题。

主要执行了三轮负载均衡:

  1. 在第一轮操作中,将 bundle 从负载最高的黄色机器 XXX.206:8081 卸载,并转移至绿色机器 XXX.83:8081。然而,在这一轮中对 bundle 执行了四次卸载操作,致使黄色机器 XXX.206:8081 的负载急剧下降,迅速转变为负载最低的 broker,从而遭遇了过度卸载的问题

  2. 在第二轮操作中,将 11 个 bundle 从负载最高的蓝色机器 XXX.32:8081 卸载,并分配至同样处于高负载状态的绿色机器 XXX.83:8081 以及低负载的机器 XXX.206:8081。在此过程中,出现了过度卸载的情况,导致蓝色机器 XXX.32:8081 成为负载最低的 broker;同时,也存在过度加载的问题,即错误地将 bundle 分配给了高负载的绿色机器 XXX.83:8081。

  3. 在第三轮操作中,将 bundle 从负载最高的绿色机器 XXX.83:8081 卸载并重新加载至蓝色机器 XXX.32:8081 后,集群才进入均衡状态,整个过程共计耗时 30 分钟。

借助 broker 日志,我们能够更为深入地洞察上述过程:

在第一轮 bundle unload 的 10 分钟内,可以观察到系统始终将 XXX.206:8081 判定为高载 broker,并持续从该节点卸载 bundle,最终引发了过度卸载的问题。追根溯源,这是由于历史均值打分算法的特性,使得 XXX.206:8081 的打分变化极为缓慢。即便该节点已经卸载了 bundle,且其真实负载也随之改变,但由于得分依然居高不下,所以仍被持续判定为高载 broker,进而不断被卸载 bundle 。

而第二轮bundle unload时,从最高载的XXX.32:8081身上卸载bundle,但是遇到了过度加载的问题,将bundle卸载到了同样高载的XXX.83:8081身上。

至此,我们已经用实验验证了ThresholdShedder + LeastResourceUsageWithWeight的两个核心缺陷:

  • 过度加载问题

  • 过度卸载问题

这两个问题因都因为历史打分算法而变得严重,过程中也可以看出ThresholdShedder + LeastResourceUsageWithWeight的负载均衡速度并不快,由于错误的负载均衡决策,往往需要反复地执行负载均衡最终才能稳定下来。

Last updated

Was this helpful?