导语 | 本文介绍了部分高功能网络计划,包含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的多种传输形式。

解锁tRPC高性能密码:网络方案简介!

因为RDMA定位为高功能网络传输,一起也为了简化硬件的规划,一般来说,RDMA会避免如软件TCP那样杂乱的可靠性规划,而是极其依靠底层传输网络的可靠性。

根据不同的传输网络,RDMA的详细实现分为几类:

解锁tRPC高性能密码:网络方案简介!

解锁tRPC高性能密码:网络方案简介!

另外补充说明:

  • 尽管RoCE v1/2依靠融合融合以太网,也即无损传输,不过也有部分厂商的优化实现,能够减轻对无损传输的依靠。
  • Linux kernel 4.9+中,实现了Soft-RoCE,也即软件版别的RoCE v2,首要用于测验、学习。

(二)RoCE v2 v.s. iWARP

在以太网环境,首要可选项为RoCE v2和iWARP,相关比照如下:

解锁tRPC高性能密码:网络方案简介!

现在来看,现在的机房网络建设中,对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等。

解锁tRPC高性能密码:网络方案简介!

如前述,一个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

解锁tRPC高性能密码:网络方案简介!

  • io_uring(Proactor)

解锁tRPC高性能密码:网络方案简介!

  • 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,腾讯后台开发工程师。