Linux 网络原理与分析
本文侧重点在于讲解 Linux 内核协议栈网络相关的内容,而 TCP/IP 网络模型的内容不会过多提及。
了解更多网络相关的原理知识请参考《计算机网络》。
- 网络性能指标
- 应用层
- QPS(每秒请求数)
- 套接字缓冲区大小
- DNS 响应延迟
- 响应时间
- 错误数
- 传输层
- TCP 连接数
- 全连接
- 半连接
- TIMEWAIT
- 连接跟踪数
- 重传数
- 丢包数
- 延迟
- 网络层
- 丢包数
- TTL
- 拆包
- 链路层
- PPS(每秒网络帧数)
- BPS(每秒字节数)
- 丢包数
- 错误数
网络模型
OSI 网络模型:即来自国际标准化组织制定的开放式系统互联通信参考模型(Open System Interconnection Reference Model),分为七层,其各自负责:
应用层:为应用程序提供统一的接口。
表示层:把数据转换成兼容接收系统的格式。
会话层:维护计算机之间的通信连接。
传输层:为数据加上传输表头,形成数据包。
网络层:数据的路由和转发。
数据链路层:MAC 寻址、错误侦测和改错。
物理层:在物理网络中传输数据帧。
TCP/IP 网络模型:Linux 中具体实现的四层网络模型。
应用层:向用户提供一组应用程序,比如 HTTP、FTP、DNS 等。对应 OSI 模型的应用层、表示层和会话层。
传输层:端到端的通信,比如 TCP、UDP 等。
网络层:网络包的封装、寻址和路由,比如 IP、ICMP 等。
网络接口层:网络包在物理网络中的传输,比如 MAC 寻址、错误侦测以及通过网卡传输网络帧等。对应 OSI 模型的数据链路层和物理层。
网络传输时,数据包会按照协议栈对上层数据逐层进行处理,然后封装该层的协议头,再发送给下一层(在原有的负载前后增加固定格式的元数据)。
由于物理链路中不能传输任意大小的数据包,网络接口配置的最大传输单元(MTU,以太网中默认值为 1500)规定了最大的 IP 包大小。
Linux 内核中的网络协议栈也类似 TCP/IP 的四层结构:
1 | +--------------------+ |
其中网卡是发送和接收网络包的基本设备。在系统启动时,网卡通过内核中的网卡驱动程序注册到系统中。在网络收发过程中,内核通过中断与网卡进行交互。
网络收发流程
网络包接收
网卡接收到网络帧:
通过 DMA 把包放到收包队列中。
通过硬中断告知中断处理程序已收到网络包。
网卡中断处理程序为网络帧分配内核数据结构(sk_buff),将其拷贝到 sk_buff 缓冲区中。
通过软中断通知内核收到了新的网络帧。
内核协议栈从缓冲区中取出网络帧,通过网络协议栈从下到上逐层处理。
DMA(Direct Memory Access):在内存和 I/O 设备进行数据传输时,经过独立的协处理器(Co-Processor)DMAC(DMA Controller)辅助处理,而无需经过 CPU 控制。
网络协议栈解析:
链路层:检查报文合法性,找出上层协议类型(比如 IPv4),再去除帧头帧尾,交给网络层。
网络层:取出 IP 头,判断网络包下一步走向:交给上层处理或转发等。当确认这个包要发送到本机后,即取出上层协议类型(比如 TCP),去除 IP 头再交给传输层。
传输层:取出 TCP/UDP 头后,根据
<源 IP、源端口、目的 IP、目的端口>
四元组作为标识,并把数据拷贝到对应的 Socket 的接收缓存中。
随即应用程序可以通过 Socket 接口读取到新接收的数据。
网络包发送
与接收相反,应用程序调用 Socket API(比如 sendmsg
)发起系统调用发送网络包。
进入内核态的套接字层,把数据包放到 Socket 发送到缓冲区中。
网络协议栈从 Socket 发送缓冲区中取出数据包,再按照 TCP/IP 栈从上到下逐层处理:比如增加 TCP 头、IP 头,执行路由查找下一跳 IP、按照 MTU(Maximum Transmission Unit)分片等。
分片后的网络包再送到网络接口层进行物理地址寻址,以找到下一跳的 MAC 地址;再添加帧头和帧尾放到发包队列中。
随后发起软中断通知驱动程序,由驱动程序通过 DMA 从发包队列中读出网络帧,通过物理网卡把它发送出去。
套接字
套接字可屏蔽 Linux 内核中不同协议的差异,为应用程序提供统一访问接口。
每个套接字都有读写缓冲区:
读缓冲区缓存远端发来的数据,读缓冲区满就不能再接收新的数据。
写缓冲区缓存要发出去的数据,写缓冲区满,应用程序写操作就会被阻塞。
性能指标
分析网络问题常参考以下指标:
带宽:链路的最大传输速率,单位通常为 b/s。常用带宽有 1000M、10G、40G、100G 等。
吞吐量:表示单位时间内成功传输的数据量,单位通常为 b/s(比特 / 秒)或者 B/s(字节 / 秒)。其受带宽限制,网络的使用率 == 吞吐量 / 带宽。
延时:表示从网络请求发出后一直到收到远端响应所需的时间。可以表示为建立连接需要的时间(比如 TCP 握手延时),或一个数据包往返所需的时间(比如 RTT)等。
传输速率:一般以 PPS(Packet Per Second,包 / 秒)衡量,即以网络包为单位的传输速率,常用于评估网络转发能力,比如硬件交换机通常可以达到线性转发(即 PPS 可以达到或者接近理论最大值),基于 Linux 服务器的转发则容易受网络包大小的影响;而对 TCP 或 Web 服务,更多会用并发连接数和每秒请求数(QPS,Query per Second)等指标反映实际应用程序的性能。
其中带宽跟物理网卡配置是直接关联的,只是实际带宽会受限于整个网络链路中最小的模块。而“网络带宽测试”实际上是测试吞吐量。
除此之外还关心网络可用性(网络能否正常通信)、并发连接数(TCP 连接数量)、丢包率(丢包百分比)、重传率(重新传输的网络包比例)等。
网络配置
分析网络问题需要查看网络接口的配置状态,使用 ifconfig
、ip
命令(net-tools/iproute2):
1 | ifconfig eth0 |
网络 I/O 异常状态:
errors:错误数据包数,校验错误、帧同步错误等。
dropped:丢弃数据包数。数据包已经收到了 Ring Buffer,但因为内存不足等原因丢包。
overruns:超限数据包数。网络 I/O 速度过快,导致 Ring Buffer 中的数据包来不及处理(队列满)而导致的丢包;
carrier:发生 carrirer 错误的数据包数。比如双工模式不匹配、物理电缆出现问题等。
collisions:碰撞数据包数。
套接字信息
使用 netstat
、ss
查看套接字信息:
1 |
|
如果接收队列(Recv-Q)和发送队列(Send-Q)的值不为 0,说明有网络包的堆积发生。当 Socket 的状态为:
Established:Recv-Q 表示套接字缓冲未被应用程序取走的字节数(即接收队列长度),Send-Q 表示还没有被远端主机确认的字节数(即发送队列长度)。
Listening:Recv-Q 表示全连接队列的长度,Send-Q 表示全连接队列的最大长度。
全连接:服务器收到了客户端的 ACK、完成了 TCP 三次握手,然后把这个连接放到全连接队列中。全连接中的套接字还需要被 accept()
系统调用取走,服务器才可以开始真正处理客户端请求。
半连接:未完成 TCP 三次握手的连接,服务器收到客户端 SYN 包后会把它放到半连接队列中,再向客户端发送 SYN+ACK 包。
协议栈信息
使用 netstat
或 ss
查看协议栈信息:包括 TCP 协议的主动连接、被动连接、失败重试、发送和接收的分段数量等。
1 | netstat -s |
网络质量统计信息
使用 sar
可查看网络统计信息,比如网络接口(DEV)、网络接口错误(EDEV)、TCP、UDP、ICMP 等:
1 | sar -n DEV 1 |
其中网络接口的使用率:半双工模式下为 (rxkB/s+txkB/s)/Bandwidth,全双工模式下为 max(rxkB/s, txkB/s)/Bandwidth。
使用 ethtool
可查询带宽(单位 Gb/s 或 Mb/s,注意是比特):
1 | ethtool eth0 | grep Speed |
使用基于 ICMP 协议的 ping
可测试远程主机的连通性和延时:
1 | ping -c3 114.114.114.114 |
优化方法
从 C10K、C100K、C1000K、C10M 问题入手可以更好理解 Linux 网络工作原理。
从 C1000K 开始,依靠单机支撑就需要仔细考虑:
从物理资源的角度:处理大量请求需要配备大内存、万兆网卡,以及基于多网卡绑定以承载大吞吐量。
从软件资源的角度:大量的连接也会占用大量的软件资源,如文件描述符、连接状态跟踪(CONNTRACK)、网络协议栈缓存(比如套接字读写缓存、TCP 读写缓存)等。
从优化的角度:中断处理处理成本也很高,需要多队列网卡、中断负载均衡、CPU 绑定、RPS/RFS(软中断负载均衡到多个 CPU 核上),以及将网络包的处理卸载(Offload)到网络设备(如 TSO/GSO、LRO/GRO、VXLAN OFFLOAD)等各种硬件和软件的优化。
I/O 模型优化
当物理资源足够,首先考虑的是 I/O 模型:如何在一个线程内处理多个请求、如何节省资源地处理用户请求。
I/O 多路复用是著名的并发解决方案,其提供两种 I/O 事件通知方式:
水平触发:只要文件描述符可以非阻塞地执行 I/O 就会触发通知。即应用程序可随时检查文件描述符的状态,然后再根据状态进行 I/O 操作。
边缘触发:只有在文件描述符的状态发生改变(I/O 请求达到)时才发送一次通知。此时应用程序需要尽可能多地执行 I/O,直到无法继续读写才可以停止。如果 I/O 没执行完,或因为某种原因未来得及处理,这次通知就会丢失。
I/O 多路复用也有多种实现方法:
非阻塞 I/O + 水平触发通知:select 和 poll 从文件描述符列表中找出可以执行 I/O ,再进行真正的读写。由于 I/O 是非阻塞的,一个线程中就可以同时监控一批套接字文件描述符,达到单线程处理多请求的目的。但也存在以下问题:
需要对文件描述符列表进行轮询,请求数多时会比较耗时。
select 使用固定长度的位相量表示文件描述符集合,有最大描述符数量的限制(32 位系统 1024);轮询检查套接字状态,处理耗时 O(N)。
poll 使用不定长数组存放文件描述符,没有最大描述符数量的限制(只受系统文件描述符限制),但也需要轮询文件描述符列表。
调用 select 和 poll 时需要把文件描述符集合从用户空间传入内核空间,由内核修改后再传出到用户空间中,存在切换成本。
非阻塞 I/O + 边缘触发通知:Linux 2.6 新增的 epoll 使用 红黑树 在内核中管理 文件描述符,不需要应用程序在每次操作时都传入传出;使用事件驱动机制,只关注有 I/O 事件发生的文件描述符,而不是轮询扫描整个集合。
异步 I/O(Asynchronous I/O):Linux 2.6 新增的异步 I/O 允许应用程序同时发起多个 I/O 操作,在 I/O 完成后系统以事件通知(比如信号或者回调函数)告知应用程序前来查询结果。然而在较长时间内都不完善(比如 glibc 提供的异步 I/O 库),且使用难度较高。
工作模型优化
I/O 多路复用还可以结合不同工作模型使用:
主进程 + 多个 worker 子进程
Nginx 反向代理的原理就是基于此:主进程用于初始化套接字,执行 bind()
+ listen()
后创建多个子进程、管理其生命周期,每个子进程都通过 accept()
或 epoll_wait()
来处理相同套接字。
惊群效应:当网络 I/O 事件发生时,多个进程被同时唤醒,但实际上只有一个进程来响应这个事件,其他被唤醒的进程都会重新休眠。
accept()
(Linux 2.6 中解决)和epoll_wait()
(Linux 4.5 中通过 EPOLLEXCLUSIVE 解决)。Nginx 在每个 worker 进程中增加全局锁(
accept_mutex
),worker 进程需要先竞争到锁才会加入到 epoll 中,确保只有一个 worker 子进程被唤醒。
可以用线程代替进程:主线程负责套接字初始化和子线程状态的管理,而子线程则负责实际的请求处理。线程的调度和切换成本比较低,再进一步把 epoll_wait()
都放到主线程中,保证每次事件都只唤醒主线程,子线程只需负责后续的请求处理。
监听到相同端口的多进程
所有的进程监听相同端口,并开启 SO_REUSEPORT
选项(Linux 3.9+),由内核将请求负载均衡到监听进程中。
内核确保只有一个进程被唤醒,不会出现惊群问题。
DPDK 和 XDP
在 C10M 问题中,单靠常规软硬件优化已经难以满足需求。
其根本原因是 Linux 内核协议栈工作太繁重:
网卡硬中断 -> 中断处理程序 -> 网卡软中断 -> 内核协议栈 -> 网络协议栈 -> 应用程序的路径太长,导致网络包处理难以优化。
DPDK(Data Plane Development Kit,数据平面开发套件)是用户态网络标准,其跳过内核协议栈、由用户态进程轮询处理网络接收:
PPS 非常高的场景中,查询时间比实际工作时间少很多,绝大部分时间都能处理网络包。
跳过内核协议栈后省去了繁杂的处理路径,应用程序可针对具体场景优化网络包处理逻辑,不需要关注所有细节。
通过大页、CPU 绑定、内存对齐、流水线并发等多种机制,优化网络包的处理效率。

XDP(eXpress Data Path):是 Linux 内核提供的高性能网络数据路径,它允许网络包在进入内核协议栈之前就进行处理。XDP 底层和 bcc-tools 一样,都是基于 Linux 内核的 eBPF 机制实现。其对内核的要求比较高(Linux 4.8+),并且不提供缓存队列。基于 XDP 的应用程序通常是专用的网络应用,如 IDS(入侵检测系统)、DDoS 防御、 cilium 容器网络插件等。

性能测试
基准测试
测试前应确定待评估的应用程序网络性能属于协议栈哪一层。
转发性能
包括网络接口层和网络层,通常关注每秒可处理的网络包数 PPS,特别是 64B 小包的处理能力。
使用 hping3
工具可测试网络包处理能力的性能,但更常用的是内核自带的 pktgen,其作为一个内核线程运行,需要加载 pktgen 内核模块后再通过 /proc
文件系统来交互:
1 | 需要配置 pktgen 内核模块(即 CONFIG_NET_PKTGEN=m)后重新编译内核才可以使用。 |
pktgen 在每个 CPU 上启动一个内核线程,可通过 /proc/net/pktgen
下的同名文件与线程交互;pgctrl
用于开启和停止测试。
假设一台机器通过 eth0 网卡向另一台机器发包:
1 |
|
一段时间测试完成后,可以从 /proc
获取结果:
1 |
|
测试结果可以参照千兆交换机的 PPS:线速(满负载、无差错转发)PPS 即 1000Mbit 除以以太网帧的大小,1000Mbps/((64+20)*8bit) = 1.5 Mpps
(20B 为以太网帧前导和帧间距的大小)。
TCP/UDP 性能
一些应用直接基于 TCP/UDP 构建服务,适合使用 iperf
和 netperf
测试吞吐量。安装 iperf3:
1 | apt -y install iperf3 |
目标机器上启动 iperf3 服务端:
1 | -s 启动服务端,-i 汇报间隔,-p 监听端口 |
在另一台机器上运行 iperf3 客户端:
1 | -c 启动客户端(指定目标服务器 ip),-b 目标带宽(单位是bits/s),-t 表示测试时间,-P 并发数,-p 目标服务器监听端口 |
在服务端上查看输出:
1 | [ ID] Interval Transfer Bandwidth |
HTTP 性能
webbench
、ab
(Apache 自带)等都是常用的 HTTP 压力测试工具,主要测试 HTTP 服务的每秒请求数、请求延迟、吞吐量以及请求延迟的分布情况等。安装 ab:
1 | apt install -y apache2-utils |
使用 ab
测试 Nginx 性能:
1 | -c 并发请求数,-n 总请求数 |
应用负载性能
工具本身的性能对测试至关重要。通过以上工具测试不能直接表示应用程序的实际性能,其与用户的实际请求很可能不一致。比如用户请求往往附带各种负载(payload),会影响 Web 应用程序内部的处理逻辑从而影响最终性能。
因此测试还要求性能工具本身可以模拟用户的请求负载,常用的工具有 wrk、TCPCopy、Jmeter、LoadRunner 等(后两者甚至提供脚本录制、回放、GUI 等功能)。
wrk 内置 LuaJIT,可以用来实现复杂场景的性能测试。在调用 Lua 脚本时可将 HTTP 请求分为三个阶段,即 setup、running、done:
1 | setup: |
比如可以在 setup 阶段,为请求设置认证参数:
1 | -- auth.lua |
再启动测试:
1 | 源码安装 |
优化总结
性能优化首先是要确定目标,不同应用中每个指标的优化标准、优先级都不同:
对于 NAT 网关而言,其直接影响整个数据中心的网络出入性能,所以通常需要达到或接近线性转发,PPS 是最主要的性能目标。
对于数据库、缓存等系统而言,目的是快速完成网络收发,即延迟是主要的性能目标。
对于 Web 服务而言,需要同时兼顾吞吐量和延迟。
应用层
即优化 I/O 模型、工作模型以及应用层网络协议。
选用网络模型:
使用 I/O 多路复用 epoll 取代 select 和 poll。
使用异步 I/O(比较复杂)。
选用工作模型:
主进程(管理网络连接)+ 多个 worker 子进程(实际的业务处理)。
监听到相同端口的多进程模型。所有进程监听相同接口,开启 SO_REUSEPORT 选项,由内核负责进程的负载均衡。
协议优化:
使用长连接取代短连接:可显著降低 TCP 连接建立成本,在每秒请求次数较多时效果非常明显。
使用内存来缓存不常变化的数据:可降低网络 I/O 次数,同时加快应用程序的响应速度。
使用 Protocol Buffer 等序列化的方式,压缩网络 I/O 的数据量,可提高应用程序的吞吐。
使用 DNS 缓存、预取、HTTPDNS 等方式减少 DNS 解析的延迟,并提升网络 I/O 整体速度。
套接字层
为了提高网络的吞吐量,通常需要调整缓冲区的大小。
增大每个套接字的缓冲区大小 net.core.optmem_max。
增大套接字接收缓冲区大小 net.core.rmem_max 和发送缓冲区大小 net.core.wmem_max。
增大 TCP 接收缓冲区大小 net.ipv4.tcp_rmem 和发送缓冲区大小 net.ipv4.tcp_wmem(三个数值分别是 min,default,max,系统会根据设置自动调整 TCP 接收 / 发送缓冲区的大小,UDP 同理)。
修改网络连接行为的配置项:
为 TCP 连接设置 TCP_NODELAY 可禁用 Nagle 算法。
为 TCP 连接开启 TCP_CORK 可让小包聚合成大包后再发送(会阻塞小包发送)。
使用 SO_SNDBUF 和 SO_RCVBUF 可分别调整套接字发送缓冲区和接收缓冲区大小。
传输层
主要时优化 TCP 和 UDP 协议。首先要了解 TCP 基本原理(比如流量控制、慢启动、拥塞避免、延迟确认)以及状态流转:

TCP
TIME_WAIT 状态优化:对于请求量较大的场景,可能会看到大量处于 TIME_WAIT 状态的连接占用内存和端口资源。
增大处于 TIME_WAIT 状态的连接数量 net.ipv4.tcp_max_tw_buckets ,并增大连接跟踪表的大小 net.netfilter.nf_conntrack_max。
减小 net.ipv4.tcp_fin_timeout 和 net.netfilter.nf_conntrack_tcp_timeout_time_wait ,让系统尽快释放其所占用的资源。
开启端口复用 net.ipv4.tcp_tw_reuse。被 TIME_WAIT 状态占用的端口还能用到新连接中。增大本地端口的范围 net.ipv4.ip_local_port_range 以支持更多连接、提高整体并发能力。
增加最大文件描述符数量。使用 fs.nr_open 和 fs.file-max 分别增大进程和系统的最大文件描述符数;或在应用程序的 systemd 配置文件中设置应用程序的最大文件描述符数 LimitNOFILE。
缓解 SYN FLOOD:
增大 TCP 半连接最大数量 net.ipv4.tcp_max_syn_backlog ,或开启 TCP SYN Cookies net.ipv4.tcp_syncookies 绕开半连接数量限制(不可同时使用)。
减少 SYN_RECV 状态连接重传 SYN+ACK 包次数 net.ipv4.tcp_synack_retries。
Keepalive 优化:长连接场景通常使用 Keepalive 检测 TCP 连接状态,以便对端连接断开后自动回收。系统默认的 Keepalive 探测间隔和重试次数一般无法满足应用程序的性能要求。
缩短最后一次数据包到 Keepalive 探测包的间隔时间 net.ipv4.tcp_keepalive_time。
缩短发送 Keepalive 探测包的间隔时间 net.ipv4.tcp_keepalive_intvl。
减少 Keepalive 探测失败后,一直到通知应用程序前的重试次数 net.ipv4.tcp_keepalive_probes。
UDP
增大套接字缓冲区大小以及 UDP 缓冲区范围。
增大本地端口号的范围。
根据 MTU 大小调整 UDP 数据包大小,减少或避免分片。
需要注意优化手段之间的冲突,比如服务器端开启 Nagle 算法、客户端开启延迟确认,很容易导致网络延迟增大;在 NAT 服务器上开启 net.ipv4.tcp_tw_recycle 容易导致各种连接失败。
网络层
主要是对路由、 IP 分片以及 ICMP 等进行调优。
从路由和转发的角度出发:
在需要转发的服务器中(比如 NAT 网关或使用 Docker 容器时),开启 IP 转发,即设置 net.ipv4.ip_forward = 1。
调整数据包的生存周期 TTL,比如设置 net.ipv4.ip_default_ttl = 64。而增大该值会降低系统性能。
开启数据包的反向地址校验,比如设置 net.ipv4.conf.eth0.rp_filter = 1。可以防止 IP 欺骗,并减少伪造 IP 带来的 DDoS 问题。
从分片的角度出发:最主要是调整 MTU 的大小。
通常根据以太网标准设置,网络帧最大为 1518B,去掉以太网头部 18B 后剩余 1500 即为 MTU。在使用 VXLAN、GRE 等叠加网络技术会使原来的网络包变大,MTU 也要相应增大。
很多网络设备支持巨帧,还可以把 MTU 调大为 9000,以提高网络吞吐量。
比如使用 VXLAN,在原来报文的基础上,增加了 14B 的以太网头部、 8B 的 VXLAN 头部、8B 的 UDP 头部以及 20B 的 IP 头部,因此交换机、路由器等的 MTU 要增大到 1550,或封包前的 MTU(比如虚拟化环境中的虚拟网卡)缩小到 1450。
从 ICMP 的角度出发:为避免 ICMP 主机探测、ICMP Flood 等网络问题,可通过内核选项限制 ICMP 行为。
禁止 ICMP 协议,即设置 net.ipv4.icmp_echo_ignore_all = 1,外部主机无法通过 ICMP 探测主机。
禁止广播 ICMP,即设置 net.ipv4.icmp_echo_ignore_broadcasts = 1。
链路层
主要是优化网络包的收发、网络功能卸载以及网卡选项。
网卡收包后调用中断处理程序(特别是软中断)需要消耗大量的 CPU,而将中断处理程序调度到不同的 CPU 上执行可以显著提高网络吞吐量。
为网卡硬中断配置 CPU 亲和性(smp_affinity),或者开启 irqbalance 服务。
开启 RPS(Receive Packet Steering)和 RFS(Receive Flow Steering),将应用程序和软中断的处理调度到相同 CPU 上,可以增加 CPU 缓存命中率,减少网络延迟。
利用网卡的功能:在内核中通过软件处理的功能转移到网卡中。
TSO(TCP Segmentation Offload)和 UFO(UDP Fragmentation Offload):在 TCP/UDP 协议中直接发送大包;而 TCP 包的分段(按照 MSS 分段)和 UDP 的分片(按照 MTU 分片)功能由网卡来完成 。
GSO(Generic Segmentation Offload):在网卡不支持 TSO/UFO 时,将 TCP/UDP 包的分段延迟到进入网卡前再执行。可以减少 CPU 的消耗,以及在发生丢包时只重传分段后的包。
LRO(Large Receive Offload):在接收 TCP 分段包时,由网卡将其组装合并后再交给上层网络处理。在需要 IP 转发时下不能开启 LRO,如果多个包的头部信息不一致,LRO 合并会导致网络包的校验错误。
GRO(Generic Receive Offload):修复了 LRO 的缺陷并且更为通用,同时支持 TCP 和 UDP。
RSS(Receive Side Scaling):也称为多队列接收,基于硬件的多个接收队列来分配网络接收进程,使得让多个 CPU 来处理接收到的网络包。
VXLAN 卸载:让网卡完成 VXLAN 的组包功能。
优化网络接口:可提升网络吞吐量。
开启网络接口的多队列功能。每个队列可以用不同的中断号调度到不同 CPU 上执行,从而提升网络的吞吐量。
增大网络接口的缓冲区大小以及队列长度等,提升网络传输的吞吐量(可能导致延迟增大)。
使用 Traffic Control 工具为不同网络流量配置 QoS。
绕过内核协议栈:
DPDK:跳过内核协议栈,直接由用户态进程轮询处理网络请求。再结合大页、CPU 绑定、内存对齐、流水线并发等多种机制,优化网络包的处理效率。
XDP:内核自带,在网络包进入内核协议栈前就对其进行处理。
关于工具和参数的选用,可以参考下表:




参考
分析案例可参考: