IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

记录一个软中断问题

火丁笔记 2013-11-01 13:56:41 累计浏览 16,957 次
本机暂存

   前些天发现XEN虚拟机上的Nginx服务器存在一个问题:软中断过高,而且大部分都集中在同一个CPU,一旦系统繁忙,此CPU就会成为木桶的短板。

   在问题服务器上运行「top」命令可以很明显看到「si」存在异样,大部分软中断都集中在 1 号CPU上,其它的CPU完全使不上劲儿:

shell> top
Cpu0: 11.3%us,  4.7%sy,  0.0%ni, 82.5%id,  ...  0.8%si,  0.8%st
Cpu1: 21.3%us,  7.4%sy,  0.0%ni, 51.5%id,  ... 17.8%si,  2.0%st
Cpu2: 16.6%us,  4.5%sy,  0.0%ni, 77.7%id,  ...  0.8%si,  0.4%st
Cpu3: 15.9%us,  3.6%sy,  0.0%ni, 79.3%id,  ...  0.8%si,  0.4%st
Cpu4: 17.7%us,  4.9%sy,  0.0%ni, 75.3%id,  ...  1.2%si,  0.8%st
Cpu5: 23.6%us,  6.6%sy,  0.0%ni, 68.1%id,  ...  0.9%si,  0.9%st
Cpu6: 18.1%us,  4.9%sy,  0.0%ni, 75.7%id,  ...  0.4%si,  0.8%st
Cpu7: 21.1%us,  5.8%sy,  0.0%ni, 71.4%id,  ...  1.2%si,  0.4%st

   查询一下软中断相关数据,发现主要集中在 NET_RX 上,猜测是网卡问题:

shell> watch -d -n 1 'cat /proc/softirqs'
                CPU0       CPU1       CPU2 ...       CPU7
      HI:          0          0          0 ...          0
   TIMER: 3692566284 3692960089 3692546970 ... 3693032995
  NET_TX:  130800410  652649368  154773818 ...  308945843
  NET_RX:  443627492 3802219918  792341500 ... 2546517156
   BLOCK:          0          0          0 ...          0
BLOCK_IOPOLL:      0          0          0 ...          0
 TASKLET:          0          0          0 ...          0
   SCHED: 1518716295  335629521 1520873304 ... 1444792018
 HRTIMER:        160       1351        131 ...        196
     RCU: 4201292019 3982761151 4184401659 ... 4039269755

   补充:有一个查看中断(Interrupt)的top风格小工具 itop ,推荐试试。

   确认一下宿主机上的网卡信息,发现其运行在单队列模式下:

shell> grep -A 10 -i network /var/log/dmesg
Initalizing network drop monitor service
Intel(R) Gigabit Ethernet Network Driver - version 3.0.19
igb 0000:05:00.0: Intel(R) Gigabit Ethernet Network Connection
igb 0000:05:00.0: eth0: (PCIe:2.5GT/s:Width x4) 00:1b:21:bf:b3:2c
igb 0000:05:00.0: eth0: PBA No: G18758-002
igb 0000:05:00.0: Using MSI-X ... 1 rx queue(s), 1 tx queue(s)
igb 0000:05:00.1: Intel(R) Gigabit Ethernet Network Connection
igb 0000:05:00.1: eth1: (PCIe:2.5GT/s:Width x4) 00:1b:21:bf:b3:2d
igb 0000:05:00.1: eth1: PBA No: G18758-002
igb 0000:05:00.1: Using MSI-X ... 1 rx queue(s), 1 tx queue(s)

   接着确认一下网卡的中断号,因为是单队列,所以只有一个中断号 45:

shell> grep eth /proc/interrupts | awk '{print $1, $NF}'
45: eth0

   知道了网卡的中断号,就可以查询其中断亲缘性配置「smp_affinity」:

shell> cat /proc/irq/45/smp_affinity
02

   这里的 02 实际上是十六进制,表示 1 号CPU,计算方法如下(参考资料):

          Binary       Hex 
  CPU 0    0001         1 
  CPU 1    0010         2
  CPU 2    0100         4
+ CPU 3    1000         8
  -----------------------
  both     1111         f

   说明:如果 4 个CPU都参与中断处理,那么设为 f;同理 8 个CPU的就设置成 ff:

shell> echo ff > /proc/irq/45/smp_affinity

   此外还有一个类似的配置「smp_affinity_list」:

shell> cat /proc/irq/45/smp_affinity_list
1

   两个配置是相通的,修改了一个,另一个会跟着变。不过「smp_affinity_list」使用的是十进制,相比较「smp_affinity」的十六进制,可读性更好些。

   了解了这些基本知识,我们可以尝试换一个CPU试试看会发生什么:

echo 7 > /proc/irq/45/smp_affinity_list

   再通过「top」命令观察,会发现处理软中断的CPU变成了 7 号CPU。

   说明:如果希望多个CPU参与中断处理的话,可以使用类似下面的语法:

echo 3,5 > /proc/irq/45/smp_affinity_list
echo 0-7 > /proc/irq/45/smp_affinity_list

   坏消息是对单队列网卡而言,「smp_affinity」和「smp_affinity_list」配置多CPU无效。

   好消息是Linux支持RPS,通俗点来说就是在软件层面模拟实现硬件的多队列网卡功能。

   首先看看如何配置RPS,如果CPU个数是 8 个的话,可以设置成 ff:

shell> echo ff > /sys/class/net/eth0/queues/rx-0/rps_cpus

   接着配置内核参数rps_sock_flow_entries(官方文档推荐设置: 32768):

shell> sysctl net.core.rps_sock_flow_entries=32768

   最后配置rps_flow_cnt,单队列网卡的话设置成rps_sock_flow_entries即可:

echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt

   说明:如果是多队列网卡,那么就按照队列数量设置成 rps_sock_flow_entries / N 。

   做了如上的优化后,我们再运行「top」命令可以看到软中断已经分散到了两个CPU:

shell> top
Cpu0: 24.8%us,  9.7%sy,  0.0%ni, 52.2%id,  ... 11.5%si,  1.8%st
Cpu1:  8.8%us,  5.1%sy,  0.0%ni, 76.5%id,  ...  7.4%si,  2.2%st
Cpu2: 17.6%us,  5.1%sy,  0.0%ni, 75.7%id,  ...  0.7%si,  0.7%st
Cpu3: 11.9%us,  7.0%sy,  0.0%ni, 80.4%id,  ...  0.7%si,  0.0%st
Cpu4: 15.4%us,  6.6%sy,  0.0%ni, 75.7%id,  ...  1.5%si,  0.7%st
Cpu5: 20.6%us,  6.9%sy,  0.0%ni, 70.2%id,  ...  1.5%si,  0.8%st
Cpu6: 12.9%us,  5.7%sy,  0.0%ni, 80.0%id,  ...  0.7%si,  0.7%st
Cpu7: 15.9%us,  5.1%sy,  0.0%ni, 77.5%id,  ...  0.7%si,  0.7%st

   疑问:理论上讲,我已经设置了RPS为ff,应该所有 8 个CPU一起分担软中断才对,可实际结果只有两个,有知道原因的请赐教,但是不管怎么说,两个总好过一个。

   此外,因为这是一台Nginx服务器,所以通过「worker_cpu_affinity」指令可以配置Nginx使用哪些CPU,如此一来我们便可以绕开高负载的CPU,对性能会有一些帮助。

   补充:如果服务器是NUMA架构的话,那么「numactl -cpubind」可能也会有用。

   最后,推荐看看香草总结的一些关于软中断方面的资料工具,很全面。

同分类推荐文章

  1. 从零重建 macOS 开发机:可复现的环境初始化流程 (2026-06-14 20:36:00)
  2. 百度物理网络监控工具开源第二弹:毫秒级监控工具 baize,让你的网络问题无处遁形 (2026-06-11 08:10:28)
  3. How to Set Up Homebrew Tap for Private CLI Tools: A Complete Guide (2026-05-27 02:13:03)

查看更多 DevOps 文章 →

建议继续学习

  1. 配置Nginx+uwsgi更方便地部署python应用 (累计阅读 107,167)
  2. 搜狐闪电邮箱的 Nginx/Postfix 使用模式 (累计阅读 33,897)
  3. 解析nginx负载均衡 (累计阅读 16,625)
  4. Go Reflect 性能 (累计阅读 14,157)
  5. server日志的路径分析 (累计阅读 11,241)
  6. Nginx模块开发入门 (累计阅读 11,172)
  7. 检查nginx配置,重载配置以及重启的方法 (累计阅读 10,897)
  8. Cacti 添加 Nginx 监控 (累计阅读 10,645)
  9. fsockopen 异步处理 (累计阅读 10,346)
  10. 使用Squid缓存视频 (累计阅读 10,339)