共计 3087 个字符,预计需要花费 8 分钟才能阅读完成。
导语 | 本文介绍了局部高性能网络计划,包含 RDMA、HARP、io_uring 等。从技术原理、落地可行性等方面,简要地做出剖析,心愿能对此方面感兴趣的开发者提供一些教训和帮忙。
一、背景
业务中常常会有这样的场景:
随着网卡速率的晋升(10G/25G/100G),以及局部业务对低提早的极致谋求(1ms/50us),目前的内核协定栈因为协定简单、流程简单、设计古老等因素,曾经逐步成为业务瓶颈。
业界曾经有局部 RDMA、DPDK 的实际,然而对于大多数开发者而言,仍然比拟生疏。
那么这些计划各自的场景到底怎么?是否可能为更多的业务赋能?以下是阶段性简要总结。
二、RDMA
(一)原理简介
绝对于传统的网络协议栈,RDMA 提供的要害个性即为:Kernel Bypass,也即利用专用的 NIC(网卡)进行硬件层面的协定传输、编解码(Offload),通过内存映射技术间接与用户态程序交互,从而防止了简单低效的内核中介。
基于这种设计,随之提供几个额定的重要个性:
- Zero-Copy:基于 DMA 操作,通信全程没有额定的 CPU 染指拷贝,从而升高 CPU 耗费。
- 稳固低提早:因为硬件通路的可靠性,从而保障了稳固的通信提早。
- 多种传输模式:RC、RD、UC、UD 等。基于不同业务的不同可靠性和性能需求,提供相似 TCP/UDP 的多种传输模式。
因为 RDMA 定位为高性能网络传输,同时也为了简化硬件的设计,一般来说,RDMA 会防止如软件 TCP 那样简单的可靠性设计,而是极其依赖底层传输网络的可靠性。
依据不同的传输网络,RDMA 的具体实现分为几类:
另外补充阐明:
- 尽管 RoCE v1/ 2 依赖交融交融以太网,也即无损传输,不过也有局部厂商的优化实现,能够加重对无损传输的依赖。
- Linux kernel 4.9+ 中,实现了 Soft-RoCE,也即软件版本的 RoCE v2,次要用于测试、学习。
(二)RoCE v2 v.s. iWARP
在以太网环境,次要可选项为 RoCE v2 和 iWARP,相干比照如下:
目前来看,目前的机房网络建设中,对 RoCE v2 的反对更好,而 iWARP 却依然处于绝对空白的状态。
为此,以后的调研次要针对 RoCE v2,而 iWARP 依然有待摸索。
(三)业务落地
后盾业务支流协定依然是 TCP,具备运行稳固、调试工具丰盛等劣势。不过对于多数冀望高性能的业务,RDMA 也是值得思考的。
业务应用 RDMA 次要面临两方面的艰难:
- RoCE v2 无损网络的要求导致难以跨机房传输,以后腾讯机房的反对为 module 内传输(如 5 跳之内)。
- 全新的开发接口如 libverbs、UCX 等,业务软件须要进行适配。
而有些存储业务依赖多正本,网络传输须要可能逾越 MAN,甚至跨城市传输。这间接导致 RoCE v2 难以落地。
三、io_uring/socket
(一)原理简介
io_uring 是 Linux 5.1+ 中反对的异步 IO 框架,其外围劣势有:
- 真正的异步化设计(Proactor),而非如 epoll 等实质上的同步行为(Reactor)。而其关键在于,程序和 kernel 通过 SQ/CQ 两个队列进行解耦。
- 对立的异步 IO 框架,不仅反对存储、网络。因为良好的扩展性,甚至能够反对任何的零碎调用,如 openat、stat 等。
如前述,一个 io_uring 的实例,会建设一对内核和用户程序共享的队列,也即提交队列 SQ 和实现队列 CQ,两者皆为 SPSC 范型: - SQ:用户态线程生产,而后零碎调用(io_uring_enter)告诉内核(io_wq kernel thread)生产。其中元素称为 SQE。
- CQ:内核生产,而后告诉(若用户程序睡眠期待则唤醒)用户态生产。其中元素称为 CQE。
这其实是最惯例也是最经典的异步模型,在泛滥异步设计中可见。
个别状况下,CQE 和 SQE 一一对应,不过 io_uring 反对 multi-shot 模式后则不肯定如此。
另外,io_uring 反对批量生产和生产,也即间断生产多个 SQ 后,一次性告诉内核,或者继续生产 CQ 直到其空。
为了进一步优化局部场景的性能,io_uring 反对泛滥的高级个性:
- File Registration:在重复操作同一个 fd 时,减速其查找映射。
- Buffer Registration:在 read/write 等重复须要在内核和用户程序替换数据的场景,能够反复利用预注册的一批内存。
- Automatic Buffer Selection:为 Proactor read 预注册一批内存,在就绪后内核主动抉择其中一块存放数据,从而缩小内存调配开释,也节约内存资源。
- SQ Polling:使内核(io_wq)轮询 SQ 指定工夫才睡眠,从而缩小告诉的零碎调用。
- IO Polling:开启子系统(存储、网络等)的轮询模式(须要设施驱动反对),从而减速局部高速设施。另外能够配合 io_uring_enter(flag:IORING_ENTER_GETEVENTS)进行忙等。
- Multi-Shot:一次提交,屡次实现,如只有一次提交 socket accept,后续连贯到来后屡次返回。
- io_uring 在存储 IO 场景,绝对之前的阻塞 IO、glibc aio、linux aio 等,都有不错的性能晋升。
那么在网络 IO 场景呢?是否优于 epoll 等计划呢?
(二)测试数据
通过调研,在出名开源软件中,暂未发现间接采纳 io_uring 进行网络 IO 的计划,如 seastar/nginx 等都没有官网反对,既然可借鉴较少,那么就自行测试。
因为 io_uring 还处于欠缺阶段,而且对于网络 IO 的反对也有多种形式。目前咱们梳理出其中 3 种:
- Proactor:io_uring 间接 recv/send。
- Reactor:io_uring 接管 socket_fd(POLL_ADD)后再 recv/send。
- io_uring 接管 epoll_fd 后再 epoll_wait 再 RECV/SEND:门路繁琐,揣测性能不佳,间接略过。
为此,咱们针对前两种 io_uring 模型,以及罕用的 epoll 模型,进行测试比照。
为了利用更多的 io_uring 个性,测试采纳以后最新 kernel(5.15)。测试模型如下:
- 通信协议:tcp echo
- 服务模型:单线程,异步并发
- 压测客户端:多线程,每个线程一个连贯同步测试
- 数据:包大小为 512B
- 测试环境:本机通信 loopback 接口
epoll
- io_uring(Proactor)
- io_uring(Reactor)
目前网上的很多程序采纳此形式。不过从实践上剖析,应该 epoll 性能靠近,故暂未测试。
(三)数据分析
通过比照、剖析以上的测试数据,能够失去以下论断:
- io_uring 在网络 IO 方面,并不比 epoll 性能弱小。网络 IO 的次要瓶颈还是在于内核协定栈的开销。
io_uring 即便开启内核轮询,在负载低时可升高延时,而满载性能晋升不显著,反而节约了 CPU 资源。
(四)业务落地
在 Linux 网络 IO 场景中,io_uring 并不比 epoll 带来额定的性能晋升。这与存储 IO 不同。
不过值得思考的是,如果一个零碎中同时存在网络 IO 和存储 IO,比照以下两种形式:
- 网络 IO 采纳 epoll,存储 IO 采纳 io_uring(可联合 eventfd 与 epoll 配合)
- 网络 IO、存储 IO 都采纳 io_uring。
从实践上剖析,形式 2 能够依赖 io_uring 批量提交等优化,从而进一步缩小零碎调用,是否能够带来性能晋升呢?
这部分须要进一步测试剖析。
四、总结
以上简略介绍了 RDMA、io_uring/socket 等计划,各有优缺点以及场景限度。后续将介绍 DPDK 的计划,敬请期待。
作者简介
quintonwang,腾讯后盾开发工程师。