首页 > 编程知识 正文

动态负载均衡算法,怎么做负载均衡

时间:2023-05-04 15:44:45 阅读:22102 作者:156

背景

在SPDK中,每个CPU内核都对应于reactor,并且创建的线程在reactor中运行。

figure1corereactor-thread对应关系

默认情况下,reactor始终以轮询模式运行,以提供最高效的处理。 但是,在reactor空闲时,总是进行轮询,因此会浪费资源。 另外,另一个reactor可能正在执行超出其自身负载的大量工作。 将部分空闲reactor线程移动到空闲reactor将大大提高效率。 或者,如果空闲的reactor使用中断模式,则可以大大减少资源的损失。 这产生了spdk的scheduler模块。

通常,在空闲状态下,调度器可以将reactor切换到“中断模式”。 在Linux上,这是使用epoll实现的,但可能会降低CPU利用率,降低事件发生时的响应速度。 计划程序大大提高了重量轻或变化大的工作负载的效率。

计划器动态旨在提高能效和CPU利用率,使您可以更好地动态管理reactor上的线程,特别是在工作负载显示出随着时间的推移变化很大的情况下。

SPDK_TOP

在介绍scheduler之前,我将向您介绍spdk验证cpu利用率的工具spdk_top。

SPDK _ top APP应用程序类似于标准top,通过spdk轻量级线程和轮询实时反馈CPU核心的使用情况。 spdk _ top APP应用程序使用RPC命令调用收集性能指标并将其显示在报告中。 这使您可以分析和确定代码是否有效运行,从而调整实现并从spdk中获取更多信息。

为什么经典的top实用程序不适用于SPDK? SPDK设计为轮询模式,并分配给在SPDK APP应用程序的每个CPU核心上执行的reactor线程,以调度spdk轻量级线程和轮询。 因此,标准Linux top实用程序对分析轮询模式(如SPDK )的APP应用程序的CPU利用率没有帮助。 这是为了报告分配的CPU资源只有100%被使用。 spdk_top实用程序是为了分析和报告用于执行实际工作和仅轮询工作的CPU周期而开发的。 此实用程序依赖于添加到轮询的工具来跟踪工作和轮询的进行时间。 spdk_top实用程序从轮询中获取细粒度指标,并分析和报告每个轮询、线程和核心指标。

启动spdk _ top APP应用程序(只有在spdk上启动了目标时才能执行) :

$SPDKDIR/build/无言的花瓣/spdk_top

基本操作

spdk_top窗口底部的菜单提供了许多用于更改显示数据的选项。 每个菜单项都有一个与方括号相关联的键。

Switch tab [1-3]-用于选择线程/轮询/核心选项卡。

Sorting [s]-用于按列对排序弹出窗口中显示的数据进行排序。

Total / Interval [t] -将所有选项卡上的显示值更改为total time (在spdk APP应用程序启动后测量)或Interval time (在上次刷新后测量)。

选择线程后,按Enter可查看详细信息。 然后,可以按 ESC 键关闭弹出窗口。

33558 www.Sina.com /提供详细的帮助信息

help [h]

Scheduler dynamic

Core 状态表述如果当前core中没有活动线程,请将相应的reactor切换到中断模式。 (如果当前酷睿具有活动线程,则切换到pol

ling mode);

2. 当线程的busy时间间隔除以当前线程的一个周期的百分比小于SCHEDULER_LOAD_LIMIT时,当前线程状态为idle;

3. 当线程的busy时间间隔除以当前线程的一个周期的百分比大于SCHEDULER_LOAD_LIMIT时,当前线程状态为busy;

线程调度原理

1. 当创建线程的活跃时间百分比小于SCHEDULER_LOAD_LIMIT(代码中设定为20)时,该线程为idle状态,此时该线程将移动到main core上。

Figure 2  balance 原理

示例:

启动一个target

test/event/scheduler/scheduler和它的rpc plugin是测试例程,在此用来评估观测scheduler行为,实际应用中用实际需要启动的target即可。

$SPDKDIR/test/event/scheduler/scheduler -m 0xF -p 2 --wait-for-rpc &

scripts/rpc.py framework_set_scheduler dynamic

scripts/rpc.py framework_start_init

这时,启动spdk_top,可以观察到当前只有app_thread(即启动的target)一个线程,并且在我们指定的main core(core2)上。

接着创建4个idle线程(活跃时间占比分为0)

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n idle0 -m 0x1 -a 0

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n idle1 -m 0x2 -a 0

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n idle2 -m 0x4 -a 0

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n idle3 -m 0x8 -a 0

之后,我们可以观察到,虽然创建时指定了这些线程绑定不同的core,但最终仍通过scheduler将这些线程全部分配在core2(main core)上:

当main core上不存在活动线程时,该 CPU 内核的频率将随着负载的降低而降低。与其他reactor对应的所有 CPU 内核都保持在最大频率。

因此,当前的reactor并没有活跃线程,所以此时main core处于低功率状态:

2.当前线程活跃占比大于SCHEDULER_LOAD_LIMIT时,当前线程的状态为busy,scheduler将会为当前线程找一个最合适的reactor,然后将其移动过去。Main core应尽量处于空闲状态,只有当线程的执行时间超过所有线程空闲时间的总和时,main core才能包含活动线程。

1)scheduler调度的目标reactor只能在target绑定的core(即启动target时设置的cpumask对应的core)上的reactor中进行选择。

2)调度的目标reactor必须有足够的空间能放下该线程。

3)调度的目标reactor应是当前polling mode的reactor中最空闲的(先排除interrupt mode的reactor,除非没有合适的才会选用)。

4)当符合以上条件时,如果 main core所对应的reactor可以容纳下当前线程,则应将当前线程移动到main core上。

示例:

创建一个活跃占比为50的线程,根据调度原则此时该线程应分配在core0上:

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n busy0 -a 50

我们再创建一个活跃占比为40的线程:

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n busy1 -a 40

通过spdk_top可以看出,busy1分配在core2(main core)上。

5)当main core容纳不了该线程时,则优先选择合适的core中core id最小的core。

示例:

在之前的基础上再创建一个活跃占比为40的线程:

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n busy2 -a 40

此时,core0、core1、core3都是空闲状态,core0 id最小,则优先分配在core0上。

6)当前core如果超出限制时,则之外的任一 core 都比当前core要更合适。对于超过限制的内核,将线程放在最不忙的内核上以平衡线程。

限制条件:

a.当前core无线程或单线程

b.没有正在运行的线程,即busy时间为0

c.完成的工作少于限制(SCHEDULER_CORE_LIMIT  95)

示例:

先清除之前所有的线程,然后在core1上创建线程busy0:

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n busy0 -m 0x2 -a 50

再在core0上创建busy1,活跃时间占比为30:

rpc_cmd --plugin scheduler_plugin scheduler_thread_create -n busy1 -m 0x1 -a 30

发现busy1被调度到了core1上,这是因为core0上并没有活动线程,此时应处于interrupt mode,因此core1比core0更适合去容纳busy1。

7 )如果没有找到更合适的,则不发生移动,该线程仍在当前core上。

3.调度流程图

4. 当reactor没有调度的spdk_threads 时,它会切换到中断模式并停止主动轮询。在足够多的线程变为活动状态后,reactor将切换回轮询模式并再次为其分配线程。

5. 如果cpu支持变频的话,则可根据需要改变main core的频率。

变频规则:

1)如果该线程不在main core上,那么为main core设置默认频率。

示例:

我们先创建一个活跃占比为10 的线程,此时观察spdk_top,发现该线程被分配在main core(core2)上,此时core2的频率为1000Mhz。

之后我们再创建一个活跃占比为50的线程,将被分配在core0上,此时main core(core2)将升至默认频率2300MHz。

2)如果main core上busy时间大于idle时间,那么为main core进行升频操作。

3)其他情况则为main core进行降频操作(main core为idle,且其他core上无线程)。

示例:

将除app_thread之外的其他线程都销毁掉,我们再观察spdk_top,发现main core(core2)的频率降频至1000MHz。

至此scheduler动态平衡的原理及流程规则全部讲完。

结语

Scheduler_dynamic 实现自动化动态平衡资源,是我们最终的目标,这样就可以极大程度上帮我们合理利用资源,提高工作效率的同时也可以在一定程度上延长设备寿命。同时,spdk_top也是一个非常棒的工具,可以让我们真正地看到资源的使用情况,并针对性地做出准确的分析及合理去改变设备的运行状态。目前两者都处于试验状态,并在不断地完善中。

参考资料

SPDK官网文档:

https://spdk.io/doc/spdk_top.html

https://spdk.io/doc/scheduler.html

《SPDK负载均衡初探》Xiaodong, Liu

转载须知

DPDK与SPDK开源社区

公众号文章转载声明

推荐阅读

2021美国峰会系列二 | SPDK与云原生

基于英特尔平台的三星5G核心网高性能UPF 305 Gbps解决方案

SPDK 负载均衡初探

基于DPDK的设备虚拟化框架

点点“赞”“在看”,给我充点儿电吧~

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。