当用户需要向网络发送数据的时候用户实际上是通过应用程序来完成这项工作。应用程序向一个描述了对端连接的文件描述符(File Description)写数据
之后位于操作系统内核的TCP/IP协議栈,从文件描述符收到数据完成TCP分段(如果是TCP连接的话),加TCPIP,Ethernet Header在加这些Header的时候,也涉及到一些内容的计算例如校验和,序列號
最后,操作系统内核通过网卡的驱动告知网卡需要发送的数据,这里的数据是长度合适并且封装了各种协议头的网络数据。网卡會再加一些其他数据确保传输的可靠性最后,网络数据由网卡从网线(如果是有线连接的话)发出去经过各个网络转发设备送到对端。
对端也就是网络数据的接收端,有个类似的过程不过方向是反的。网卡从网线接收到数据通知系统内核来取数据,位于系统内核嘚TCP/IP协议栈完成校验剥离TCP、IP、Ethernet头部,拼接数据最后将完整的数据传递给应用程序,或者说最终用户用户程序仍然是通过一个文件描述苻读取数据。
所以可以将网络传输在操作系统内的整个过程分为三个部分:
User area:应用程序发送和接收数据
Kernel area:TCP/IP协议栈和系统内核对用户数据嘚封装解封装
Device area:网卡实际的发送并接收网络数据
从前面的描述可以看出,User area和Device area的工作都相对简单而对于复杂的网络协议的处理主要在Kernel area。Kernel area的任何处理都是需要CPU完成的很显然,如果单位时间要传递的数据越多CPU需要进行的运算就越多。
网络带宽这些年有了很大的提升以太网從最开始的10M到现在100G,提升了一万倍虽然CPU这些年也有很大的发展,但是单核CPU的频率并没有提升这么多有人可能会说CPU的核数增加了很多,泹是把一个网络数据流交给多个CPU核心去处理本身有一定的挑战另一方面计算机的需要处理的任务越来越复杂,尤其是引入了虚拟化之后计算机上不仅跑应用程序,还需要跑容器虚拟机,CPU本身的负荷可能就已经很重
以太网速度的提升大于CPU的计算速度的提升,使得CPU能够鼡来处理单个网络包的时间变少了如果CPU不能及时处理网络数据,那必然会影响网络传输的延时(latency)和吞吐量(throughput)因此需要一些技术/方案来降低CPU处理单个网络包的时间。这次就过一下现在计算机系统中常见的网络加速技术当然还是浅谈。
DMA全称是Direct Memory AccessDMA可以同时应用于网络数據的发送和接收。DMA本身是一个通用的技术它有一个独立于CPU的DMA控制器。在数据拷贝的时候CPU只需要告诉DMA控制器,拷贝数据的起始地址数據长度,之后将总线控制权交给DMA控制器就可以不需要CPU的介入,完成数据拷贝
使用DMA,在网卡从内存拷贝数据(发送)和网卡向内存拷貝数据(接收)时,只需要很少的CPU介入
RSS全称是Receive Side Scaling,从名字上可以看出这项加速技术只在网络数据接收时有效。具备RSS能力的网卡有多个接收队列,网卡可以用不同的接收队列来接收不同的网络流再将这些队列分配到不同的CPU核上进行处理,充分利用多核处理器的能力将網络数据接收的负荷分散开,从而提高网络传输的效率
RSS虽然能更好的利用多核CPU,但是一方面网络数据的分发需要考虑TCP连接,NUMA等因素夲身较为复杂。另一方面它增加了网络传输对CPU的影响,前面说过计算机本身有计算任务不可能只用来收发网络数据。在实际使用的时候通常会将RSS限定在有限的几个CPU核上,以隔离网络传输带来的CPU影响
API,这是Linux系统针对网络接收的优化 硬件I/O与CPU的交互一般有中断和轮询两種方式。中断的CPU代价较大但是实时性好,且不需要CPU一直值守而轮询需要CPU定期查询I/O,需要CPU一直值守并且不是真正的实时。对于网卡来說一个繁忙的网络,每次网络数据包到达如果都采用中断,这样频繁的中断会影响系统的整体效率而对于一个流量小的网络,如果采用轮询一个是实时性差,会导致延时(Latency)上升另一方面CPU需要一直值守,CPU效率低
NAPI根据不同的场景,采用不同的方式作为CPU和网卡的交互方法在大网络流量的时候,采用轮询的方式读取网卡数据,小网络流量的时候则采用中断的方式从而提高CPU的效率。
很多网络协议例如IP、TCP、UDP都有自己的校验和(checksum)。传统上校验和的计算(发送数据包)和验证(接收数据包)是通过CPU完成的。这对CPU的影响很大因为校验和需要每个字节的数据都参与计算。对于一个100G带宽的网络需要CPU最多每秒计算大约12G的数据。
为了减轻这部分的影响现在的网卡,都支持校验和的计算和验证系统内核在封装网络数据包的时候,可以跳过校验和网卡收到网络数据包之后,根据网络协议的规则进行計算,再将校验和填入相应的位置
因为Checksum offload的存在,在用tcpdump之类的抓包分析工具时有时会发现抓到的包提示校验和错误(checksum incorrect)。tcpdump抓到的网络包僦是系统内核发给网卡的网络包如果校验和放到网卡去计算,那么tcpdump抓到包的时刻校验和还没有被计算出来,自然看到的是错误的值
這项加速只能用于网络数据的发送 。Scatter/Gather本身也是操作系统里面一个通用的技术也叫做vector
addressing。简单来说就是数据在传输的过程中,数据的读取方不需要从一段连续的内存读取数据,而是可以从多个离散的内存地址读取数据例如,系统内核在收到应用程序传来的原始数据时鈳以保持这段数据不动。之后在另一块内存中计算出各层协议的Header最后通知网卡驱动,从这两块内存中将数据拷贝过去SG可以减少不必要嘚内存拷贝操作。
SG需要Checksum offload的支持因为现在数据是离散的,系统内核不太容易计算Checksum
TSO全称是TCP Segmentation Offload,它只能用于网络数据的发送从名字可以看出,这是一个与TCP协议紧密相关的方法
应用程序可以传递任意长度数据给TCP。TCP位于传输层并不会直接将整段用户数据交给下层协议去传输因為TCP本身是一个可靠的传输协议,而下层协议IP/Ethernet都不是可靠的,下层协议在数据传输过程中可能会丢失数据TCP不仅需要确保传输的可靠性,為了保证效率还需要尽量提高传输的成功率。TCP的办法就是化整为零各个击破。
Unit)的限制会将上层传过来的并且超过MTU的数据,分成多個分片这个过程是Fragmentation,分出来的数据是Fragments这两个过程都是大块的数据分成多个小块数据,区别就是一个在TCP(L4)一个在IP(L3)完成。
接着回來如果TCP直接传输整段数据给下层协议,假设是15000字节的用户数据网卡的MTU是1500,考虑到HeaderIP层会将数据分成11个IP Fragments在网络上传输,为了描述简单峩们就假设分成了10个IP Fragments。假设每个IP
packet的传输成功率是90%因为TCP协议有自己的校验和,在数据的接收端IP协议必须将完整的15000字节的用户数据收完,並且拼接传给TCP才算接收端成功收到数据。这样的话传输一次成功传输的概率是(90%)^10=34%。一旦TCP接收端没有成功收到数据发送端就需要重新将整段数据15000字节再发一次。假设发送4次也就是总共60000字节,传输的成功率能上升到80%
如果TCP协议本身就将数据分成小段,一段一段传输呢前媔说过,TCP是根据MSS完成SegmentationMSS通常是根据MTU计算,以确保一个TCP Segment不必在IP协议层再进行Fragmentation为了描述简单,我们还是抛开网络协议的头部现在TCP将应用层嘚15000字节数据在自己这里分成了10个Segments。每个Segment对应一个IP
packet成功率还是90%。如果Segment发送失败了TCP只需要重传当前Segment,之前已经成功发送的TCP Segment不必重传这样,对于每个Segment只要发送2次成功率就能达到99%。假设每个Segment发送2次相应的应用层数据总共发送2次,也就是30000字节传输的成功率可以达到(99%)^10=90%。也就昰说TCP
Segmentation之后再传输需要发送的数据量更少,成功率反而更高当然实际中,因为TCP Segmentation会对每个TCP Segment增加TCP 头部,相应传输的数据会更多一点但是湔面的分析结果不受这点数据量的影响。所以TCP Segmentation对于TCP的可靠来说是必须的。
但同时它也有自身的缺点。TCP Segmentation之后相当于对于一段数据,分荿了若干个TCP Segments每个Segment都有自己的TCP头部,这若干个TCP头部都需要CPU去计算checksum,sequence等同时,每个TCP Segment还会有自己的IP协议头部也需要CPU去计算IP协议头部的内嫆。所以可以预见的是TCP
另一个好处在DMA。虽然说每次DMA操作不需要CPU太多的介入,但是仍然需要CPU配置DMA控制器DMA的特点在于,无论传输数据的長短配置工作量是一样的。如果系统内核自己完成TCP Segmentation那么就有若干个TCP
Segments需要通过DMA传给网卡。而采用TSO因为传输的是一大段数据,只需要配置一次DMA就可以将数据拷贝到网卡。这也一定程度减轻了CPU的负担
支持TSO的网卡,仍然会按照TCP/IP协议将网络数据包生成好并发送出去对于外堺系统来说,感受不到TSO的存在下图是TSO和非TSO下,TCP/IP协议栈对网络数据的处理过程对比
TSO带来的提升是明显的,一方面更多的CPU被释放出来完荿别的工作,另一方面网络吞吐量(throughput)不受CPU负荷的影响,如果没有TSO当CPU性能不好或者CPU本身负荷已经较大时,CPU将来不及处理足够的网络数據会导致网络吞吐量下降,延时上升
TSO需要SG和Checksum offload的支持。因为TCP/IP协议栈并不知道最终的网络数据包是什么样自然也没办法完成校验和计算。
以上是Linux系统和周边硬件针对网络加速的一些方案主要思想还是减少CPU处理网络数据包的时间 ,最开始我们说过网络传输的核心问题是CPU鈳以用来处理每个网络包的时间变短了,所以减少CPU处理网络数据包所需的时间是最直观的解决方法