spdk qos机制:
spdk qos核心机制是定时刷新的qos配额。刷新的qos配额可以用于qos queue中的bdev_io提交,也可用于新接收到的bdev_io提交,当qos配额用完后,新接收到的bdev_io需要在qos queue中排队,等待新的qos配额刷新后,才可向驱动提交。qos配额的刷新周期为SPDK_BDEV_QOS_TIMESLICE_IN_USEC(默认1ms)。qos相关任务如下图:
考虑到spdk任务是不可抢占的,每个qos配额刷新任务不可能刚好是SPDK_BDEV_QOS_TIMESLICE_IN_USEC间隔执行,因此当两次qos配额刷新间隔大于若干个qos刷新周期时,需要分配多个qos配额。qos配额刷新见bdev_channel_poll_qos流程,如下图:
spdk目前共支持4种qos,分别是IOPS qos,BPS qos,BPS rqos,BPS wqos。
IOPS qos是对每秒IOPS最大读写数进行限制的qos。接收到的bdev_io需要先获取qos配额后,才能向驱动提交,每个bdev_io需要获取1个iops配额。
BPS qos是对每秒最大带宽进行限制的qos。接收到的bdev_io需要先获取qos配额后,才能向驱动提交,每个bdev_io需要获取bdev_io数据量的byte配额。
BPS rqos是对每秒最大读带宽进行限制的qos。接收到的读bdev_io需要先获取qos配额后,才能向驱动提交,每个读bdev_io需要获取读bdev_io数据量的byte配额。
BPS wqos是对每秒最大写带宽进行限制的qos。接收到的写bdev_io需要先获取qos配额后,才能向驱动提交,每个写bdev_io需要获取写bdev_io数据量的byte配额。
4种qos均放在spdk_bdev_qos->rate_limits数组里面,因此新增加qos也很简单,可直接在数组里面新增qos类型,比如IOPS rqos(IOPS读qos)和IOPS wqos(IOPS写qos)。增加新类型qos后,在bdev_qos_set_ops,bdev_qos_is_iops_rate_limit等qos接口里面也需要增加对应逻辑。
当多种qos同时配置时,qos生效策略为都通过才算qos通过,其中任何一种qos要求不满足,就排队不向驱动提交。qos生效策略可见下图bdev_qos_io_submit函数。
为支持多核访问同一个bdev的qos需求,spdk采用io任务委托提交的方式向bdev层提交io。具体方式是在多个核中选取一个io任务提交核用于执行bdev_io提交,其余未被选中的核通过bdev_io_submit提交bdev_io时,需要使用spdk_thread_send_msg向提交核发送一个消息,提交核收到消息后使用_bdev_io_submit执行提交,当判断需要qos时,使用bdev_qos_io_submit向qos提交bdev_io,qos完成限速后再通过bdev_io_do_submit向bdev驱动提交request。完整的提交流程见下图:
bdev qos机制可能带来不连续突发请求的性能抖动,若qos设置太小,主机每次突发请求都较大(默认qos配额1ms刷新一次,突发请求大于千分之一的qos配额),会导致qos的poll提交生效,某些io的时延可能达到一个qos配额刷新周期时间(默认1ms)。
spdk qos命令:
spdk支持动态调整bdev qos参数,使用bdev_set_qos_limit命令,若相关limit参数设置为0,则相关limit取消(SPDK_BDEV_QOS_LIMIT_NOT_DEFINED),具体命令帮助信息如下图。
实验验证:
理论知识分析完毕,接下来实践一下spdk qos功能。模拟本地盘云主机场景,先搭建qemu虚拟机通过vhost-user协议跑一下环境IO性能。环境搭建可参考spdk软件包中doc/vhost.md文档,步骤略过。仅介绍搭建好的环境情况如下,物理机spdk中创建一个1G大小的内存盘Malloc0,然后通过Vhost-BLK挂载到虚拟机,虚拟机硬盘随机读性能约80W IOPS。
物理机上执行命令bdev_set_qos_limit,把IOPS限制到1W,执行命令如下:
然后看一下虚拟机的性能,可以看到IOPS已经下降到1W以下,此时带宽为38M。IOPS qos限制正确生效。
接下来,再限制一下带宽,看看带宽qos对IOPS业务的影响。把带宽限制到20M,物理机上执行命令如下:
相对于1W IOPS,20M带宽限制更严格。看一下环境,虚拟机IOPS业务性能的确是受到更严格的带宽限制影响,带宽下降到20M以下,IOPS下降到5000左右。带宽qos限制正确生效。
接下来解除带宽限制,注意限制参数填写0即可。
可以看到IOPS恢复到1W IOPS。
接下来解除IOPS限制,注意限制参数填写0即可。
可以看到IOPS恢复到80W IOPS。实验完毕。