一、引言
在金融交易、工业控制、高性能网络等要求微秒级时延的系统中,“中断”常常是影响尾延迟(Tail Latency)的关键因素之一。 在普通系统里,中断带来的几十微秒抖动并不算问题,但在低延迟系统中,即使是 几微秒的不可控波动,都可能导致性能抖动、订单错失。 本文将从原理、影响、排查等维度,系统性介绍中断对低延迟系统的影响。
二、低延迟系统的特点
低延迟系统的目标是在极短时间内完成处理,并保持响应时间高度稳定。这类系统通常有以下共性,使得它们对中断格外敏感:
1. 强调确定性
低延迟系统不仅追求“快”,更追求“稳定”。它希望每一次响应时间都尽量一致,不出现无规律的波动。而中断的触发往往具有不确定性,会破坏这种稳定性。
2. 核心资源为业务专用
为了减少干扰,低延迟系统通常会预留部分 CPU 只运行核心业务逻辑。
任何外来的系统任务、中断或调度行为进入这些核心,都会破坏业务线程的专注度,引发延迟尖刺。
3. 对尾延迟特别敏感
很多系统关注平均延迟,但低延迟系统还关注最差情况(例如 99.9%、99.99% 延迟)。
因此哪怕偶尔一次中断引发几十微秒的延迟,也会被放大成系统性能问题。
4. 对干扰高度敏感
低延迟系统通常关闭节能、规避抢占、避免内核后台任务等。
在这种极限优化状态下,即使是非常小的系统活动,例如一次定时器中断,也可能打断业务流程,从而产生可观的抖动。
三、中断如何影响低延迟系统?
中断在低延迟系统中的影响主要体现在三个层面:
1. 抢占执行、打断业务线程
中断会中止正在运行的业务代码,引起:
- CPU L1/L2 缓存污染
- pipeline flush
- TLB miss 增加
- 业务线程指令乱序恢复
对于微秒级任务,这种打断是“毁灭性”的。
2. 导致不可预测的时延尖刺
中断不连续、不规则,例如:
- 某个 IRQ 在负载高时突然 flood
- 某个 housekeeping 定时器每几秒被触发
- 某个软中断在 backlog 到阈值后被 forced 执行
这些都会导致业务端出现 几微秒到几十微秒的波动。
3. 软中断(SoftIRQ)更隐蔽
很多系统管理员只关注“硬中断”,但真正杀伤力高的是:
- NET_RX
- NET_TX
- TIMER
- TASKLET
- RCU
它们会在本 CPU 上被强制执行,且执行时长不可控,极容易破坏延迟稳定性。
四、如何排查中断对延迟的影响?
在低延迟系统中,中断是否落到了业务核心、是否存在异常增长,是判断延迟抖动来源的关键依据。
传统方式通常是直接 cat /proc/interrupts,但它不具备实时性,也难以观察变化趋势。
因此,使用自研的 irq_watch.py 脚本,实现实时监控中断变化,帮助快速定位问题。
1. irq_watch.py 的功能概述
该脚本的核心作用是:
- 实时监控指定 IRQ 或 CPU 的中断增长情况 脚本每秒读取 /proc/interrupts,计算变化量,只输出“发生变化的项”。
- 支持 CPU 或 IRQ 白名单筛选 避免全量输出带来的噪声。
- 支持稀疏 CPU(如 CPU0/7/8/9/12) 可自动解析实际在线 CPU,而不依赖连续编号。
- 支持参数格式:1,5-7,10-12 满足生产环境中常见的范围表达方式。
- 附带中断描述信息 如网卡 MSI-X、IPI、timer 等,便于快速识别来源
- 兼容 Python 2 / Python 3 适用于老旧发行版(如 RHEL7)。
2. 参数说明
脚本提供三个最常用参数:
| 参数 | 说明 |
|---|---|
-irq | 指定监控的 IRQ 号(支持范围表达式) |
-cpu | 指定监控的 CPU 核(支持范围表达式) |
-i | 刷新间隔,默认 1 秒 |
3. 示例
只监控 CPU0 与 CPU1 中断情况
./irq_watch.py -cpu 0,1
监控特定中断号(如 36、37、40–45)
./irq_watch.py -irq 36,37,40-45
监控多 CPU + 多 IRQ(组合过滤)
./irq_watch.py -cpu 0,7-9 -irq 33-50
4. 输出示例解析
以下是监控cpu0和cpu1上每秒中断的情况:
[root@instance-bguv65e0 ~]# ./irq_watch.py -cpu 0,1
2025-11-26 19:25:44
IRQ 37 CPU 0: + 10 (total 120514471) PCI-MSIX-0000:02:00.0 1-edge virtio1-req.0
IRQ 38 CPU 1: + 5 (total 117021031) PCI-MSIX-0000:02:00.0 2-edge virtio1-req.1
IRQ 45 CPU 0: + 13 (total 49011897) PCI-MSIX-0000:01:00.0 1-edge virtio0-input.0
IRQ 46 CPU 0: + 5 (total 29506292) PCI-MSIX-0000:01:00.0 2-edge virtio0-output.0
IRQ 47 CPU 1: + 13 (total 51737238) PCI-MSIX-0000:01:00.0 3-edge virtio0-input.1
IRQ 48 CPU 1: + 21 (total 56302135) PCI-MSIX-0000:01:00.0 4-edge virtio0-output.1
IRQ LOC CPU 0: + 232 (total 41007210) Local timer interrupts
IRQ LOC CPU 1: + 186 (total 540671379) Local timer interrupts
IRQ CAL CPU 0: + 3 (total 26439851) Function call interrupts
2025-11-26 19:25:45
IRQ 37 CPU 0: + 1 (total 120514472) PCI-MSIX-0000:02:00.0 1-edge virtio1-req.0
IRQ 38 CPU 1: + 4 (total 117021035) PCI-MSIX-0000:02:00.0 2-edge virtio1-req.1
IRQ 45 CPU 0: + 4 (total 49011901) PCI-MSIX-0000:01:00.0 1-edge virtio0-input.0
IRQ 46 CPU 0: + 9 (total 29506301) PCI-MSIX-0000:01:00.0 2-edge virtio0-output.0
IRQ 47 CPU 1: + 6 (total 51737244) PCI-MSIX-0000:01:00.0 3-edge virtio0-input.1
IRQ 48 CPU 1: + 7 (total 56302142) PCI-MSIX-0000:01:00.0 4-edge virtio0-output.1
IRQ LOC CPU 0: + 234 (total 41007444) Local timer interrupts
IRQ LOC CPU 1: + 166 (total 540671545) Local timer interrupts
IRQ RES CPU 0: + 1 (total 16877997) Rescheduling interrupts
IRQ CAL CPU 0: + 3 (total 26439854) Function call interrupts
2025-11-26 19:25:46
IRQ 45 CPU 0: + 4 (total 49011905) PCI-MSIX-0000:01:00.0 1-edge virtio0-input.0
IRQ 46 CPU 0: + 8 (total 29506309) PCI-MSIX-0000:01:00.0 2-edge virtio0-output.0
IRQ 47 CPU 1: + 5 (total 51737249) PCI-MSIX-0000:01:00.0 3-edge virtio0-input.1
IRQ 48 CPU 1: + 4 (total 56302146) PCI-MSIX-0000:01:00.0 4-edge virtio0-output.1
IRQ LOC CPU 0: + 200 (total 41007644) Local timer interrupts
IRQ LOC CPU 1: + 204 (total 540671749) Local timer interrupts
IRQ RES CPU 0: + 7 (total 16878004) Rescheduling interrupts
IRQ RES CPU 1: + 2 (total 20872214) Rescheduling interrupts
IRQ CAL CPU 0: + 1 (total 26439855) Function call interrupts
解释如下: IRQ:中断号(或 LOC/CAL 等 IPI 名字) CPU:发生增量的 CPU 核编号 +N:本次 interval 内增加多少次 total:累计总次数 描述:/proc/interrupts 最后一列,中断来源(网卡/磁盘/IPI/timer)
监控的中断数量没有变化会输出 (no change):
[root@instance-bguv65e0 ~]# ./irq_watch.py -irq 222
2025-11-26 19:44:35
no change
2025-11-26 19:44:36
no change
2025-11-26 19:44:37
no change
这样可大幅降低无意义噪声,便于观察异常增长。
五、典型排查场景
场景 1:业务核心是否被“脏”中断污染?
在延迟敏感的系统中,关键的业务线程往往会被绑定到固定的核心上,比如业务核心被绑定在 6,7,8,9号核心,则可以用以下指令来监测:
./irq_watch.py -cpu 6-9
场景 2:排查稀疏 CPU 布局下的中断落点
在禁用了部分核的系统中(如 CPU0/7/8/9/12 在线):
./irq_watch.py -cpu 7-12
脚本可自动识别真实在线 CPU,使排查更准确。
场景 3:观察周期性延迟尖刺是否由某 IRQ 触发
例如怀疑某个 timer 中断:
./irq_watch.py -irq LOC
或怀疑某特点中断
./irq_watch.py -irq 64-100
若被监控的中断数量周期性增长,则可以确定延迟尖刺原因。
六、irq_watch.py 的优势总结
| 能力 | 描述 |
|---|---|
| 实时检测 | 定位瞬时 spike 不再困难 |
| 增量输出 | 不输出无变化项,噪声极低 |
| CPU/IRQ 双过滤 | 灵活监控业务相关部分 |
| 稀疏 CPU 兼容 | 适配任意在线 CPU 布局 |
| 自动提取中断描述 | 快速识别来源 |
| 资源占用低 | 占用的硬件资源几乎可以忽略 |
七、如何获取?
📌 获取方式如下: 1️⃣ 关注我的微信公众号:Hankin-Liu的技术研究室 2️⃣ 发送关键词:irq watch 3️⃣ 获取脚本 4️⃣ 发送关键词:”性能调优群“,加入技术交流群,可免费解答和交流性能调优相关技术问题。
八、总结
低延迟系统需要在高度可控、可预测的环境中运行,而中断是影响系统确定性的关键因素之一。理解中断在系统中的角色、其带来的不确定性来源,以及如何持续监测其行为,是打造稳定低延迟系统的基础能力。 通过构建完善的监控机制、结合业务特性制定相应策略,并持续验证系统在实际负载下的表现,可以更好地确保低延迟系统在各种运行状态下保持一致的性能表现。中断管理不是一次性的工作,而是伴随系统运行全周期的持续任务。
📬 欢迎关注VX公众号“Hankin-Liu的技术研究室”,持续分享信创、软件性能测试、调优、编程技巧、软件调试技巧相关内容,输出有价值、有沉淀的技术干货。