S48

高性能网络

点击正文段落选定收藏或划线位置;未选定时使用屏幕内第一段。

课内目录

1 高性能网络要关注什么

高性能网络的目标,是让进程在规定的时间内完成足够多的数据交换,并且在负载增加、连接变化或局部故障时仍然可观测、可恢复。网卡标称速率只是链路能力,不能直接代表应用能力。数据从网线进入网卡后,还需要被主机处理、交给套接字,再由进程读取;发送方向也需要应用准备数据并让系统发送。如果其中某个环节排队,链路即使没有跑满,用户仍然可能感到很慢。

先分清吞吐、包速率和延迟。吞吐通常用 bit/s 表示,描述单位时间搬运的数据量;PPS 是每秒处理的包数,描述处理事件的频率;延迟描述完成某次交换需要多久。还要看丢包、重传、CPU 占用和连接失败。平均延迟适合观察整体趋势,p99 延迟可以揭示少量请求遇到的长等待。报告 p99 时应同时写出采样区间与请求数,避免把很少的样本当成稳定结论。

例如,文件分发进程发送较大的数据块,可能先遇到链路带宽上限;频繁交换短消息的服务,可能先耗尽 CPU 的包处理能力。备份进程读取文件时,如果磁盘读取慢,即使网络还有余量,发送速率也上不去。反过来,内存中的网络测试可以跑得很快,也不能证明真实文件分发同样快。要把“网络能够搬多少”与“应用能够准备、消费多少”分别测量,再把它们放回实际路径。

Linux 主机上可以先用 ip -br link 确认接口,用 ip route get <对端IP> 确认到测试目标的出口,用 ip -s link show dev <接口> 查看接口计数。接口可能叫 enp3s0,也可能是虚拟接口;名称本身不说明物理能力。测试前应记录发送端、接收端、接口、MTU、CPU 数、测试方向与背景任务。容器或虚拟机还可能经过额外接口,因此不能凭宿主机某张网卡的数值推断整个路径。

从应用目标到主机处理与链路能力
从应用目标到主机处理与链路能力

本课用 2 台已获准测试的 Linux 主机建立直觉:先观察 1 条 TCP 连接,再增加并行连接,最后判断限制来自链路、CPU 分配还是应用。这里的“高性能”始终对应明确的工作负载,例如“在规定小包负载下,接收端仍满足延迟目标”,而不是寻找适用于所有机器的调优参数。每次修改都应能够解释希望改变哪段路径,以及用什么证据判断它是否奏效。

2 RSS、RPS 与中断亲和

网卡收到数据后,需要通知 CPU 来处理。可以把接收队列理解为等待处理的入口,把 CPU 理解为负责取走任务的工人。如果所有任务集中到 1 个入口、由 1 个 CPU 忙着处理,即使其他 CPU 很空闲,整体也可能出现瓶颈。网络处理中的软中断是观察这类 CPU 工作的重要线索;初学阶段只需理解它会消耗 CPU 时间,不必深入内核执行过程。

RSS 是网卡提供的接收分流能力。支持 RSS 的网卡可以根据流的特征,把接收到的数据分配到不同接收队列。这里的流可以粗略理解为具有相同通信端点与协议的一组包。为了保持处理顺序,同一条流通常稳定落到某个队列,因此“有 8 个队列”并不表示 1 条 TCP 连接能够平均使用 8 个队列。多流测试更容易表现出 RSS 的分散效果,但实际分布仍取决于设备配置和流的组合。

中断亲和描述某个中断允许由哪些 CPU 处理。队列已经分开,并不意味着对应的通知一定分散得合理;如果多个繁忙队列的中断集中在同个 CPU,仍可能形成热点。/proc/interrupts 提供按 CPU 展开的累计中断计数,可以结合网卡名称寻找相关行,比较间隔前后的增长。单次看到某列数值很大,只说明历史累计较多,不能直接证明当前热点,判断必须依赖相同时间窗口内的增量。

RPS 是 Linux 在软件侧分配接收处理工作的机制,可以在合适场景把后续处理交给其他 CPU。它可能帮助缺少足够硬件队列的环境,也会增加跨 CPU 交接与缓存访问成本。RSS、RPS 和中断亲和解决的是相关但不同的问题:入口如何分队列、后续处理如何分 CPU、设备通知由谁接收。不能把这些开关理解成“打开越多就越快”,更不能直接复制另一台服务器的 CPU 位图。

流、接收队列与 CPU 分配的关系
流、接收队列与 CPU 分配的关系

可以用 ethtool -l <接口> 查询设备暴露的通道信息,用 ethtool -x <接口> 查询 RSS 分配信息;某些虚拟接口或设备不支持这些查询,报错表示能力或接口不适用。RPS 配置通常可从 /sys/class/net/<接口>/queues/rx-*/rps_cpus 观察,这些值是 CPU 位图。读取配置有助于解释现象,但修改前还应检查系统是否运行 irqbalance 等自动管理服务,否则人工设置可能被重新调整。

对初学者更稳妥的顺序是先测量,再提出假设,最后做可回退的修改。例如先确认负载期间某个 CPU 的软中断持续偏高,再确认对应队列和流是否集中,然后评估分散是否可能有效。若应用进程本身已经占满 CPU,调整网卡中断未必解决问题。生产系统的亲和设置还受应用线程布局影响,本课先掌握证据之间的关系,具体位图计算与更深层 CPU 拓扑优化留到有明确需求时再展开。

3 内核旁路与 DPDK 边界

常规网络应用通过套接字使用操作系统提供的网络服务。系统承担协议处理、接口管理和许多诊断能力,应用可以使用常见的读写接口。内核旁路则把部分数据收发路径移到用户态,由专用程序直接承担更多工作。DPDK 是实现这类高性能包处理的工具集合之一,常见方式包括轮询接收队列和批量处理数据包。它适合讨论包处理能力,但不能被理解为所有网络应用的通用加速按钮。

轮询意味着程序持续检查是否有数据,而不是等待每次到达都触发通知。这样可以减少部分通知开销,也可能长期占用专门的 CPU,即使业务低谷也保持较高使用率。批量处理可以摊薄每个包的固定成本,但为了凑批次而等待,又可能增加延迟。因此“CPU 更忙”未必等于浪费,“吞吐更高”也未必意味着每次交换更快。是否划算,要结合稳定负载、延迟要求与资源预算判断。

旁路还会改变运维边界。某些使用方式需要专门分配网卡端口、队列、内存和 CPU,普通工具未必能完整看到应用负责的路径。tcpdump 在常规接口上没有抓到数据,不能据此断言旁路应用没有收包;反过来,旁路程序报告成功,也不能替代应用级可用性验证。团队需要知道从哪里读取包计数、如何查询丢弃原因、如何保存日志,以及程序退出后谁来恢复设备与服务。

选择前可以提出 3 个问题:普通套接字方案是否已经被测出明确瓶颈;旁路能够减少的成本是否正是主要限制;团队能否承担新的监控、升级和故障恢复流程。如果瓶颈是文件读取、应用计算或对端限速,旁路无法消除这些限制。如果需求只是稳定传输大文件,经过合理配置的常规网络栈通常应先成为基线。只有基线证据支持进一步投入,比较专用路径才有意义。

本课不提供把业务网卡切换到旁路模式的操作命令。真正部署时,设备接管可能影响现有网络连接,需要独立管理通道和经过演练的回退流程。当前需要掌握的是责任变化:普通路径中由系统承担的部分工作,会转移给应用及其运维团队。评估报告除了记录吞吐提升,还应记录占用的 CPU、空闲时成本、故障定位时间以及版本升级要求,才能比较完整的运行代价。

4 动手:测量一次单流与多流吞吐

准备 2 台安装了 iperf3 的 Linux 主机,分别记为 A 和 B。使用允许压测的环境,并确认测试不会挤占正在运行的重要任务。以下示例测量 A 到 B 的 TCP 传输;把命令中的 192.0.2.20 替换为 B 的实际可达地址,这个文档示例地址不能直接用于真实测试。防火墙需要允许测试端口 TCP 5201,测试结束后应恢复临时增加的规则。

先在 B 上运行服务端,再在 A 上运行客户端。服务端绑定指定地址,便于明确本次测试使用的入口。下面的重定向把客户端结果保存在当前目录中;应先确认目录可写、文件名没有覆盖需要保留的记录。每次测试使用不同文件名,保留命令、时间与当时配置。

# B:把示例地址替换为 B 的测试地址
iperf3 -s -B 192.0.2.20

# A:单流,运行 30 秒,前 3 秒不计入统计
iperf3 -c 192.0.2.20 -t 30 -O 3 -P 1 --json > s48-p1.json

# A:保持其他条件相同,使用 8 条并行流
iperf3 -c 192.0.2.20 -t 30 -O 3 -P 8 --json > s48-p8.json

-P 8 表示建立 8 条并行测试流,不能解释成给原来的连接增加了 8 倍处理能力。多流可能分散到更多队列,也可能让多条连接共同利用路径容量。它还会改变连接数和调度压力,所以比较结果时必须注明并行度。运行顺序可能受到背景负载影响,建议在配置不变时各测 3 次,观察结果是否稳定,而不是只挑选最高值。基准测试报告应保留失败结果及其原因。

测试期间,A 和 B 都应观察 CPU 与接口。若安装了 sysstat,可用 mpstat -P ALL 1 按 CPU 查看利用率,特别关注 %soft;用 pidstat -u -p <进程PID> 1 观察测试进程。ip -s link 记录接口收发、错误和丢弃计数,ss -tin 提供 TCP 连接状态及相关信息。这些输出字段会随系统版本变化,先确认单位和字段含义,再把数值用于结论。

在同个测试窗口收集发送端与接收端证据
在同个测试窗口收集发送端与接收端证据

如果服务端无法启动,检查地址是否属于本机、端口是否被占用;如果客户端连接超时,先核对地址、路由、服务监听和防火墙,不要立即调整 RSS。如果可以连接但结果偏低,再查看两端 CPU、重传与链路计数。需要查看接口统计时,可以使用 ethtool -S <接口>,但字段由设备提供,应结合设备说明解释,不能把名字相近的字段当作跨设备完全相同的指标。

假设单流约为 3 Gbit/s,多流约为 8 Gbit/s,同时接收端软中断从集中在 1 个 CPU 变为分散到多个 CPU。这支持“并行流改善了处理分布”的判断,但还不足以排除其他影响。若多流吞吐提高而 p99 延迟明显恶化,也不能直接宣布方案达标。iperf3 主要测量传输吞吐,应用延迟还需要应用自己的请求或消息测试;ping 的结果也不能代替业务 p99。

最后增加反向测试,例如在客户端原命令中加入 -R,观察 B 发送、A 接收时是否同样表现良好。发送与接收能力可能不对称,2 台机器的 CPU、队列和背景负载也可能不同。完成后在服务端前台按 Ctrl+C 停止测试服务,并保存环境说明。这个实验的产物应是一组带条件的证据:测试路径、方向、流数、持续时间、吞吐、两端 CPU 和错误计数,而不是孤立的速率截图。

5 易运维与极致性能取舍

性能优化会消耗资源,也会改变团队处理故障的方式。保持常规套接字路径,通常容易接入现有监控、抓包与进程管理;增加队列、调整亲和或采用专用轮询路径,则可能提高特定负载下的能力,同时引入配置维护成本。选择时应先写清不可突破的约束,例如管理连接必须可用、升级窗口有限、节点需要与其他进程共享 CPU,再讨论能接受多少专用资源。

CPU 专用化就是典型例子。给网络处理预留 CPU,可能减少与其他任务争用,但会减少应用计算和后台任务能够使用的资源。若机器白天传输繁忙、夜间执行文件校验,把全部 CPU 都按峰值网络场景固定分配,可能拖慢夜间作业。方案需要说明预留数量、适用负载和变更方式;“当前跑分更高”不能自动说明整个运行周期更划算。

交互中的滑块使用教学模型,帮助观察包速率、每包 CPU 成本与预留 CPU 之间的关系。模型不能预测某张网卡或某个内核版本的真实性能,也不直接计算业务 p99。它表达的是资源约束:当到达工作量持续高于处理能力时,队列会增长,最终可能出现延迟或丢弃。增加处理资源可以降低模型中的压力,但实际收益还受流分布与应用能力限制。

运维成本也应有可检查的内容。配置是否保存到受管理的文件,重启后是否仍然生效,自动管理服务是否会覆盖设置,监控是否能看到每个 CPU 与接口计数,这些都应进入评审。每次变更都保留原值、修改原因、验证窗口与回退触发条件。若降低延迟的同时导致监控失去关键证据,应补齐观测后再扩大部署,避免发生问题时只剩下“网络很慢”的描述。

比较候选方案时,可以把相同工作负载下的吞吐、p99、丢包、CPU 预算和恢复耗时放在同张表里。满足目标的方案中,优先选择团队能够稳定维护的配置;当普通路径确实无法满足需求,再考虑更大的运行复杂度。这个过程没有统一的最优档位,关键在于让性能收益与承担的责任能够被解释和复现。

6 常见坑:只看带宽不看 PPS/小包

带宽相同,包越小,每秒需要处理的包通常越多。先用简化计算建立直觉:忽略链路和协议开销,1 Gbit/s 相当于每秒 125000000 字节;若每个包按 1000 字节计算,约为 125000 PPS;若按 100 字节计算,约为 1250000 PPS。后者的字节量相同,处理事件却增加到 10 倍。真实链路还包含帧头、间隔等成本,所以这些数字只是教学估算。

网络路径中有些成本随字节量增长,有些成本与包数、连接数或系统调用频率有关。因此大块数据测试跑满链路,不能证明短消息服务也能承受同样的 bit/s。测试报告应说明包长或应用消息大小、TCP 或 UDP、并发连接数、方向以及是否存在突发。使用 TCP 时,应用每次写入的数据量也不保证等于线上单个包的长度,不能只凭某次 write 的字节数推断 PPS。

另一个常见误判来自观测位置。网卡和系统可能进行分段或合并等优化,不同位置看到的包数与大小可能不同。抓包工具中的包形态,未必完全等同于线上以太网帧。入门阶段不必展开这些机制的内部实现,但要记录数据来自应用、操作系统计数还是外部链路测量,并确认口径再做比较。随意关闭相关能力来“统一数字”,可能直接改变被测系统的性能。

丢包和重传也不能混用。UDP 测试可以在接收侧报告接收情况,TCP 则可能通过重传掩盖部分底层丢失,表现为吞吐下降或延迟增加。接口丢弃计数、TCP 重传与应用超时各自描述不同位置的现象,不能机械相加。当 PPS 增加时,要同步观察 CPU 热点、接口丢弃与业务完成率,才能判断压力是否已经传递到用户可见结果。

不要直接在生产路径上发出不受限制的小包洪流。更合理的测试从较低负载开始,逐步增加,并提前规定延迟、错误率与 CPU 的停止条件。每档保留相同观测窗口,同时记录实际发送与实际接收速率。若发送端已经饱和,接收端看到的“稳定”可能只是发送端无法继续加压;若只记录平均带宽,短时间突发造成的排队也可能被整个窗口稀释。

7 案例:软中断打满单核拖垮延迟

某台 Linux 主机运行持续接收短消息的进程。负载上升后,应用 p99 从约 4 ms 增加到约 60 ms,接口接收带宽只有标称容量的约 30%,整机平均 CPU 也不高。值班人员最初怀疑应用计算变慢,但观察发现应用进程 CPU 没有相应增长,接收端某个 CPU 的 %soft 却长时间接近占满。这里的关键矛盾是整体资源看似充足,而接收路径存在局部热点。

先保存同个时间窗口内的请求速率、延迟、每 CPU 利用率和接口计数。接着比较 /proc/interrupts 中相关队列计数的增长,发现活跃接收队列的中断主要落在该 CPU。查询通道与 RSS 信息后,又发现负载虽然包含多条流,但可用队列和中断分布没有有效利用其他 CPU。这样的证据可以把调查方向收窄到接收处理分配,而不是仅凭平均 CPU 排除主机瓶颈。

从延迟升高定位到接收处理热点
从延迟升高定位到接收处理热点

此时应分别检查流、队列和 CPU。若实际上只有 1 条重流,增加队列不一定让它自动分散;若多条流已经落到多个队列,但中断仍集中,才更有理由评估亲和配置。若设备只有有限队列,软件分配也许值得测试,但仍需观察额外交接成本。不能把“看到软中断高”直接翻译成“启用 RPS”,因为症状相同,原因和适用措施可能不同。

在测试环境中,团队保存原配置,调整支持范围内的队列与亲和分配,并确认自动管理服务的策略。保持消息大小、连接数和发送速率不变后,原热点 CPU 的软中断下降,多个 CPU 分担处理,p99 回落,接口丢弃增量也减少。随后再检查应用 CPU,确认瓶颈是否只是转移到了业务线程。只有整个目标组合改善,才能把这次变更视为有效,而不是只看 CPU 图变得均匀。

上线采用少量节点验证,并设置回退条件:如果错误率增加、延迟恶化或管理通道受影响,就恢复原配置。案例最终记录“在指定短消息负载下,接收处理分配限制了能力”,而不写成“网络慢都由中断造成”。保留这个边界很重要:同样的 p99 升高,也可能由应用锁等待、文件写入、对端拥塞或路径问题引起,下次仍然需要从证据开始。

8 把网络性能目标写进方案

“网络要快”无法验收,需要改写成带条件的目标。至少说明通信双方、运行环境、方向、消息大小、连接数、持续时间与背景负载,再规定吞吐或消息完成率、延迟分位数、允许的丢失和 CPU 预算。例如“在 8 条连接、指定消息大小、持续 10 分钟的接收测试中满足目标”,比“支持高速网卡”更接近可执行要求。具体阈值应由业务需求和基线共同确定。

目标还应区分链路测试与应用测试。链路测试用于确认路径可以搬运数据,应用测试用于确认进程能按要求完成工作。如果服务需要把接收内容写入文件,应说明是否包含文件写入、是否要求持久化,以及使用什么存储条件。否则把内存接收结果当成完整服务能力,会遗漏文件系统和存储带来的限制。测量范围必须与方案承诺的范围一致。

验收不能只看通过时的峰值。应记录重复测试的波动、升压过程中何时出现排队,以及恢复正常负载后延迟能否回落。长时间运行还要观察计数增量,防止偶发丢弃被平均值遮住。对于共享主机,背景任务应被明确纳入条件;对于多个候选配置,要在相同条件下比较,避免把机器差异误判为某项调优的效果。

方案中的运维部分要写出指标来源、采样周期、负责人和回退方法。告警可以结合应用延迟、接收丢弃与每 CPU 软中断,而不是只用接口带宽百分比。配置项应标明适用接口与作用范围,并保存修改前的值。遇到设备或系统升级时,先确认能力与配置是否仍然有效,再复用旧结论,不能假定相同参数在所有版本上意义完全一致。

最后把结论写成可讨论的取舍:当前方案达到什么目标,消耗多少资源,还剩多少余量,什么负载变化会触发重新评估。如果多流可以满足整体吞吐,但业务必须使用单条连接,就应明确这个差距并继续调查;如果小包负载先达到 PPS 上限,就应把包速率作为容量约束。性能方案的价值,是让开发、系统与网络人员对同组证据形成一致理解。

9 从高性能网络走向数据中心网络架构(S49)

本课主要研究主机如何把数据接进来、交给进程并发送出去。但 2 台主机之间还存在交换设备、物理链路和共享路径。即使端点已经调优,多台发送主机同时向同个接收方向传输,也可能争用途中相同的出口。端点看到的重传和延迟只能说明问题已经影响通信,不能单凭这些现象判定瓶颈位于主机还是网络中间。

进入数据中心尺度后,容量规划要从“某张网卡有多快”转向“哪些主机之间同时通信、流量会汇聚到哪里”。备份窗口、分布式计算和文件复制可能形成不同的流量方向与突发形态。单对主机测试有助于建立基线,但不能覆盖多对主机同时运行的共享瓶颈。测试矩阵需要逐步增加通信关系,并保持端点观测,防止把主机限制混入架构判断。

本课的测量方法仍然适用:写清工作负载,记录路径与方向,比较吞吐、PPS、延迟及错误,并区分累计值和增量。不同的是,下一课需要把端点证据与网络结构联系起来,讨论容量如何共享、故障影响如何扩散,以及冗余路径能解决什么问题。当前不必提前学习动态路由协议细节,先理解主机能力与路径能力是共同决定结果的条件。

带着 3 个问题进入 S49:端点都没有明显热点时,如何识别共享路径压力;增加链路容量后,哪些通信仍可能受限;某条链路或某台设备不可用时,业务如何保持可达。回答这些问题,需要把本课关于单机处理的视角扩展为关于连接关系和故障范围的视角,才能把“机器跑得快”进一步变成“系统在真实并发与故障下仍然可用”。

放进方案里

在方案中增加“网络性能与运行边界”段落,先写服务的真实交换方式:哪些进程通信,是否包含文件读取或写入,主要方向是什么,消息大小与连接数如何分布。不要仅填写网卡速率;同时给出目标吞吐或消息完成率、p99 延迟、允许的错误与 CPU 预算,并说明测试时的背景负载。阈值应来自业务需求,无法确定的项目标为待基线测量。

验收安排分为端点传输测试与应用测试。前者用单流、多流及反向测试确认基础能力,后者覆盖实际进程和必要的文件系统操作。每组记录环境、命令、持续时间与重复次数,关联两端每 CPU 利用率、接口计数增量和应用延迟。若只有吞吐结果,应明确它尚不能证明应用延迟达标;若发送端先饱和,也应说明接收能力尚未被充分测出。

小包验收另列消息大小、目标 PPS 与突发持续时间,注明包数来自网卡还是系统计数。以同一窗口内的接收完成率、p99 和丢弃增量共同判定通过;升压结束后,确认积压能在约定时间内消退,并保存对应队列与软中断记录。

调优条目写清假设、证据和回退。只有观察到队列或 CPU 分配问题,才评估 RSS、RPS 与中断亲和;每次修改保存原值,检查自动管理策略,并使用相同负载复测。若考虑内核旁路,要补充专用资源、观测接口、设备恢复方式和升级责任,比较满足相同目标所需的完整运行成本。

上线先覆盖有限节点,规定延迟恶化、丢弃增加或管理连接异常时的回退条件。持续监控结合业务完成率、延迟、包速率和局部 CPU 热点,并定期复核小包与突发场景。最后写出重新评估的触发条件,例如消息变小、并发增大或通信方向改变,让后续容量扩展能够依据已有证据继续推进。

10 小结:下一步数据中心网络架构(S49)

高性能网络需要同时观察吞吐、PPS、延迟和处理资源。RSS、RPS 与中断亲和帮助解释接收工作如何分配,内核旁路则改变性能路径与运维责任。测量时保留单流、多流、方向和两端观测,才能把结果变成可复现的结论。

自测时尝试解释:为什么平均 CPU 不高仍可能出现网络处理瓶颈;为什么多流测试达标不能证明单流业务达标;为什么大包带宽充足仍可能无法处理小包负载。下一课 S49 将把这些端点证据放入数据中心的连接结构中,继续讨论共享容量、冗余与故障范围。

同阶段相关课

AI 答疑

默认关闭。启用后,只发送本课标题、最近阅读的屏幕内正文摘录(最多 6000 字)与本次问题。

配置自己的服务