<!-- <style>
h1 {
border-bottom: none
}
h2 {
border-bottom: none
}
h3 {
border-bottom: none
}
.md-toc {
margin-top:45px;
padding-bottom:20px;
font-size: 150%; /* 目录文字大小 */
}
</style> -->
<!-- <font size=6> <center> **SPDK 用户态 IO 多路径软件决赛文档** </center> </font> -->
<!-- <font size=5> <center> **目录** </center> </font> -->
<!-- [TOC] -->
<!-- <div STYLE="page-break-after: always;"></div> -->
# SPDK 用户态 IO 多路径软件决赛文档
## 摘要
SUMP,全称为 SPDK-USERSPACE-MULTI-PATH ,是一款致力于在 SPDK 用户态驱动框架下实现**通用多路径功能**的软件。我们通过**劫持动态链接库**的方式,在**无侵入、不修改 SPDK 原本代码**的基础上,为 SPDK 扩展一个**用户态多路径组件**,这个模块依然运行在用户态下,**拦截 SPDK 原生组件创建的远程 IO 路径**,并将其统一管理,聚合成一条高效可靠的路径,再提供给 SPDK 原生模块,让其像使用原生 IO 路径一样的方式使用这条聚合多路径,并再在此基础上进一步开发,实现**故障处理、负载均衡**等多路径功能。
SUMP 是**竞赛驱动型项目**。根据赛题 [proj113](https://github.com/oscomp/proj113-spdk-based-io-multi-path) 的要求,本项目旨在完成以下目标:
- 【基本特征】支持屏蔽冗余路径。
- 【基本特征】支持路径选择。
- 【基本特征】支持故障切换和恢复。
- 【基本特征】支持负载均衡。
- 【进阶特征】支持最优路径选择。
- 【进阶特征】负载均衡场景下,支持不同的负载均衡算法,如 round_robin 等。
我们在初赛阶段实现了路径聚合和部分故障处理的功能,可以将连接同一物理磁盘的多条冗余路径聚合成为一条路径。经过测试,我们发现 SUMP 能将 4 条冗余**路径聚合**成 1 条可靠的路径,在带宽受限(10MBps)的场景下,多路径的性能可以达到**单路径性能的 4 倍**。
我们在**决赛阶段**重点实现了**故障处理**的功能,在单条链路出现故障时,多路径模块能进行**故障切换**,继续通过其他路径提供可靠的 IO,当故障链路径重连时,多路径模块还能进行**故障恢复**,而单路径并不具备这样的功能,在出现故障时只能**被迫中断 IO**。
在**决赛阶段**,我们还重点实现了**负载均衡**的功能,包括**四种静态负载均衡算法**和**三种动态负载均衡算法**。在带宽受限、4 条路径带宽不均衡(1MBps、1MBps、100MBps、100MBps)的场景下,我们对各负载均衡算法的 IO 性能进行了测试和探究,发现**动态**负载均衡的效果远好于**静态**负载均衡,且**队列深度动态负载均衡算法**的表现最佳。
上述场景均以 NVMe-oF 存储网络协议为例,而我们的用户态多路径模块还可以对接 **iSCSI 存储网络协议**,这也是**传统内核多路径软件**的重要应用场景。在**决赛阶段**,我们使用同样的 **NVMe 磁盘**、同样的 **iSCSI 存储网络协议**、同样的队列深度**负载均衡算法**、同样带宽受限的 **4 条路径不均衡路径**和同样的 IO 规模,对比测试了用户态与内核态多路径的性能,我们的用户态多路径相较于内核态,可以有 30% 左右的性能提升。
综上所述,我们的赛题完成情况如下:
|目标|完成情况|主要工作
|-|-|-|
|【基本特征 - 初赛工作】支持屏蔽冗余路径。<br/>主机与存储通过多条链路相连,对于同一块磁盘,<br/>不同的链路均会呈现出一个磁盘设备,出现冗余,<br/>因此多路径软件需要支持冗余屏蔽功能,对用户呈现一个可用的磁盘设备。|基本完成|1. 劫持 `spdk_bdev_register` 函数,拦截上报的 `bdev` <br/>2. 基于 `TAILQ` 建立二级 `bdev` 队列,聚合 `uuid` 相同的 `bdev`<br>3. 基于 `TAILQ` 建立 `io_channel` 队列,组织起冗余 IO 路径<br>4. 向上级呈现统一的多路径 `bdev`,遵循其接口标准|
|【基本特征 - 初赛工作】支持路径选择。<br/>自动选择一条可用路径下发 IO。| 基本完成|1. 拦截上层下发的 `bdev_io`,提取多路径 `bdev` 的上下文<br/>2. 在检测到 IO 任务时遍历 `TAILQ` 块设备队列,将块设备对应的 IO 路径加入到 `TAILQ` 路径队列中<br/>3. 在 IO 任务请求提交时,从 `TAILQ` 路径队列中选择一条 `io_channel` 下发|
|【基本特征 - 初赛工作和<font color="red">决赛工作</font>】支持故障切换和恢复。<br/>当多路径软件检测到路径故障时,自动将 IO 切换到可用路径;<br/>当多路径软件检测到路径恢复后,自动将路径添加到可用路径列表。|基本完成|1. 通过 SPDK 的接口检测 IO 任务是否成功,若失败则放弃这条 `io_channel`,并重新选择路径下发 IO<br/> 2. 定期对被放弃的 `io_channel` 进行用例测试,若能成功完成 IO 任务,则重新启用这条路径|
|【基本特征 - <font color="red">决赛工作</font>】支持负载均衡。<br/>主机与存储之间通过多条 IO 路径相连,IO 可同时通过多条路径一起下发。|基本完成|1. 接收到一批 IO 请求时,循环遍历所有可用 `io_channel`,轮流选择下发 IO<br/>2. 以不同的切换速度遍历各 IO 路径,尝试寻找到最佳切换频率|
|【进阶特性 - <font color="red">决赛工作</font>】负载均衡场景下,支持不同的负载均衡算法,如 round_robin 等。|基本完成|1. 实现了4种静态负载算法(Round Robin、Random、Hash、Weight)<br/>2. 实现了3种动态负载均衡算法(Service Time、Average Rate、Queue Length)|
|【进阶特性 - <font color="red">决赛工作</font>】支持最优路径选择。<br/>自动选择一条最优路径下发 IO。|大致完成|每次选择负载均衡效果最佳的路径|
<!-- <div STYLE="page-break-after: always;"></div> -->
## 1 概述
### 1.1 项目背景及意义
存储区域网络(Storage Area Network,SAN)是企业最常用的后端存储架构,适用于**高吞吐量**和**低延迟**的业务,已经成为现代科技领域中不可或缺的重要技术。SAN 是一种连接**服务器**和**存储设备**的专用网络,其基本结构如图1所示。该技术把系统拆分为**计算结点、存储结点**两大模块,并将两者分别部署,以实现**计算功能和存储功能的解耦合**,从而在充分满足用户**高存储量需求**的同时,兼顾**应用程序性能**的提升,为用户提供了灵活、高效、安全、便利、可扩展的计算环境与计算模式。
<div style="text-align: center">
<img src="assets/fig1-SAN.png" alt="" style="width:600px;" />
</div>
<div style="text-align: center">图1 SAN 基本结构</div>
SAN 往往基于 FCP 、iSCSI 、FCoE 、FC-NVMe 等协议实现,可以帮助企业实现较多性能要求较高的业务关键型应用,如 Oracle 数据库、Microsoft SQL Server 数据库、大型虚拟桌面基础架构等。SAN 广泛应用于数据密集型的企业和组织,如金融机构、医疗保健机构、媒体和娱乐行业等。它在虚拟化环境下尤为重要,可为虚拟服务器提供高性能、可靠的存储支持。
然而,在上述过程中,**计算结点**与**存储结点**需要借助网络进行通信,完成 IO 请求与 IO 响应。如果两者之间只有一条链路,显然容�