問題
多核CPU游戲戰斗服務器高峰期時會出現網絡丟包, 發現CPU0軟中斷%si 過高,導致%id值過低觸發告警
如下圖,在線低峰期軟中斷%si 處理時間百分比高達20多,id值變低,服務器變卡和丟包,影響業務

中斷
什么是中斷?
指接收來自硬件或者軟件的信號發送給CPU和系統內核進行處理,發出這樣的信號稱為進行中斷請求(IRQ)
中斷又分為:
硬中斷:外圍硬件比如網卡發給CPU的信號
軟中斷:由硬中斷處理后對操作系統內核發出信號的中斷請求
查看中斷情況即CPU都在哪些設備上干活
通過命令cat /proc/interrupts 查看系統中斷信息,長下面這個樣子的。
第一列是中斷號,比如eth0對應的中斷號是35,后面是每個cpu對應的中斷次數。
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU70: 127 0 0 0 0 0 0 0 IR-IO-APIC-edge timer7: 15 0 0 0 0 0 0 0 IR-IO-APIC-edge8: 182900 0 0 0 0 0 0 0 IR-IO-APIC-edge rtc09: 1 0 0 0 0 0 0 0 IR-IO-APIC-fasteoi acpi23: 18575 0 0 0 0 0 0 0 IR-IO-APIC-fasteoi ehci_hcd:usb124: 0 0 0 0 0 0 0 0 DMAR_MSI-edge dmar025: 132248 0 0 0 0 0 0 0 IR-HPET_MSI-edge hpet226: 0 0 0 0 0 0 0 0 IR-HPET_MSI-edge hpet327: 0 0 0 0 0 0 0 0 IR-HPET_MSI-edge hpet428: 0 0 0 0 0 0 0 0 IR-HPET_MSI-edge hpet529: 0 0 0 0 0 0 0 0 IR-HPET_MSI-edge hpet632: 0 0 0 0 0 0 0 0 IR-PCI-MSI-edge aerdrv33: 2735198364 0 0 0 0 0 0 0 IR-PCI-MSI-edge ahci34: 1 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth035: 1157411688 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-036: 2199548159 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-137: 2210448541 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-238: 954381730 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-339: 3991435919 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-440: 2197207910 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-541: 2685654183 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-642: 2153260851 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-7NMI: 121456 40118 30875 24931 27000 26053 21459 19945 Non-maskable interruptsLOC: 3074687366 1216301963 1626527541 4049966581 4109422958 2708891166 1813301274 1373418058 Local timer interruptsSPU: 0 0 0 0 0 0 0 0 Spurious interruptsPMI: 121456 40118 30875 24931 27000 26053 21459 19945 Performance monitoring interruptsIWI: 0 0 0 0 0 0 0 0 IRQ work interruptsRES: 2454452061 1303706723 606598429 461072921 965186776 274559675 348785593 347963099 Rescheduling interruptsCAL: 216 682 679 680 583 683 667 668 Function call interruptsTLB: 19837873 5603975 5927817 4380569 12552909 11396903 7656446 6960058 TLB shootdownsTRM: 0 0 0 0 0 0 0 0 Thermal event interruptsTHR: 0 0 0 0 0 0 0 0 Threshold APIC interruptsMCE: 0 0 0 0 0 0 0 0 Machine check exceptionsMCP: 132236 132236 132236 132236 132236 132236 132236 132236 Machine check pollsERR: 15MIS: 0
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
35: 1157411688 0 0 0 0 0 0 0 IR-PCI-MSI-edge eth0-TxRx-0從上面可以看得到eth0的網卡中斷次數最多,意味着中斷請求都在CPU0上面處理,固然就會出現圖1的情況
優化
Linux系統采用中斷機制協同處理CPU與其他設備工作。網卡的中斷默認由cpu0處理,在大量請求的網絡環境下可能出現cpu0負載高,而其他cpu空閑。后來出現網卡多隊列技術解決這個問題
RSS(Receive Side Scaling)是網卡的硬件特性,實現了多隊列,可以將不同的中斷次數分發到不同的CPU上。多隊列網卡是一種技術,最初是用來解決網絡IO QoS (quality of service)問題的,后來隨着網絡IO的帶寬的不斷提升,單核CPU不能完全處滿足網卡的需求,通過多隊列網卡驅動的支持,將各個隊列通過中斷綁定到不同的核上,以滿足網卡的需求,同時也可以降低CPU0的負載,解決圖1的問題
查看網卡是否支持隊列,支持多少個隊列
awk '$NF~/eth/{print $1,$NF}' /proc/interrupts37: eth0-TxRx-038: eth0-TxRx-139: eth0-TxRx-240: eth0-TxRx-341: eth0-TxRx-442: eth0-TxRx-543: eth0-TxRx-644: eth0-TxRx-7
以上網卡eth0為例支持隊列,37-44是中斷號, 一般現在主流網卡驅動都支持多隊列,默認是7個隊列
中斷綁定
網卡支持了隊列,意味着我們就可以綁定中斷號與處理CPU之間的關系,
Linux系統默認使用irqbalance服務優化中斷分配,它能自動收集數據,調度中斷請求,但是它的分配調度機制極不均勻,不建議開啟,為了了解中斷綁定,我們把irqbalance服務關掉,手工調整綁定關系。
##相關配置文件:
/proc/irq/中斷號/smp_affinity,中斷IRQ_ID的CPU親和配置文件,16進制
/proc/irq/中斷號/smp_affinity_list,10進制,與smp_affinity相通,修改一個相應改變。
smp_affinity和smp_affinity_list修改其一即可,smp_affinity_list修改更方便
cat /proc/irq/37/smp_affinity01cat /proc/irq/38/smp_affinity_list01#上面表示01對應cpu0,可以直接修改綁定關系echo 0 > /proc/irq/37/smp_affinityecho 1 > /proc/irq/38/smp_affinityecho 2 > /proc/irq/39/smp_affinityecho 3 > /proc/irq/40/smp_affinityecho 4 > /proc/irq/41/smp_affinityecho 5 > /proc/irq/42/smp_affinityecho 6 > /proc/irq/43/smp_affinityecho 7 > /proc/irq/38/smp_affinitycat /proc/irq/37/smp_affinity_list0cat /proc/irq/38/smp_affinity_list1cat /proc/irq/39/smp_affinity_list2cat /proc/irq/40/smp_affinity_list3cat /proc/irq/41/smp_affinity_list4cat /proc/irq/42/smp_affinity_list5cat /proc/irq/43/smp_affinity_list6cat /proc/irq/44/smp_affinity_list7#此時中斷號37、38對應的處理CPU為cpu1、cpu2,top命令查看%si是否均衡分攤到0-7核CPU
支持RSS的網卡,通過上面這種方法將不同的中斷號綁定到每個CPU上實現了中斷的分配。
RPS/RFS
雖然說RSS實現了中斷的分配,但是如果隊列數 < 機器總核數 並且CPU與中斷號一一對應了,會出現軟中斷負載跑在0-7核上,其他核不處理軟中斷的情況,0-7核負載依然會很高。RSS需要硬件支持,在只支持單隊列或多隊列的環境中,RPS/RFS提供了軟件的解決方案。
RPS(Receive Packet Steering)是基於RSS軟件方式實現CPU均衡,接收包中斷的優化,是把一個或多個rx隊列的軟中斷分發到多個CPU核上,從而達到全局負載均衡的目的。
RFS(Receive Flow Steering)是RPS的擴展,由於RPS只是單純的把數據包均衡到不同的CPU上,此時如果應用程序所在CPU和中斷處理的CPU不在同一個核,將會對CPU Cache影響很大,RFS的作用就是將應用程序和軟中斷處理分配到同一個CPU
配置RPS
一個十六進制 f 表示四個CPU核,那么均衡到32核即ffffffff,經研究測試,最大只支持32核調度分配
rps_cpus='ffffffff'for rxdir in /sys/class/net/eth0/queues/rx-*doecho $rps_cpus >$rxdir/rps_cpusdone
配置RFS
RFS擴展了RPS的性能以增加CPU緩存命中率,減少網絡延遲,默認是禁用的
/proc/sys/net/core/rps_sock_flow_entries
這個值依賴於系統期望的活躍連接數,注意是同一時間活躍的連接數,這個連接數正常來說會大大小於系統能承載的最大連接數,因為大部分連接不會同時活躍。推薦值是 32768
/sys/class/net/device/queues/rx-queue/rps_flow_cnt
將 device 改為想要配置的網絡設備名稱(例如,eth0),將 rx-queue 改為想要配置的接收隊列名稱(例如,rx-0)。
將此文件的值設為 rps_sock_flow_entries 除以 N,其中 N 是設備中接收隊列的數量。例如,如果 rps_flow_entries 設為 32768,並且有 16 個配置接收隊列,那么 rps_flow_cnt 就應設為 2048。對於單一隊列的設備,rps_flow_cnt 的值和 rps_sock_flow_entries 的值是一樣的
ls /sys/class/net/eth0/queues/rx-*|grep queues|wc -l8rps_flow_cnt=32768/8=4096echo 32768 >/proc/sys/net/core/rps_sock_flow_entriesfor rxdir in /sys/class/net/eth0/queues/rx-*doecho $rps_cpus >$rxdir/rps_cpusecho $rps_flow_cnt >$rxdir/rps_flow_cntdoneecho 32768 >/proc/sys/net/core/rps_sock_flow_entries
效果
RSS+RPS+RFS 優化過后可以看到軟中斷已均分到每個CPU上,%id值均勻,現在看已經是比較充分地利用多核CPU了,不用太擔心單核出現高負載告警的問題。

