網卡中斷負載均衡

現實中的問題

隨着硬件成本的降低,我們服務器配置也越來越“上流”了,可是單臺服務器的包處理能力還是很有限,經常看到cpu負載很高, linux內核自從2.4版本之後就引入了netfilter框架,網絡數據包的處理能力很大程度上是以併發連接數來衡量的,每一個連接在內核中實際上是做了很多處理的。特別是有大量udp包處理的情況,這些udp包多是短連接,併發量又大,也就是說對cpu的耗費是非常大的。mpstat -P ALL 1:

我們從圖中可以看出cpu0處於比較繁忙的狀態,佔用率在60%-70%,已經是高負載,實際上linux內核從2.4開始就已經支持中斷數在各個cpu上的負載均衡了,很顯然我們沒有充分利用已有的多cpu資源。

 

解決之道

     我們知道,任何外設(如磁盤,網卡等)需要cpu服務時,都會拋出一箇中斷,中斷告訴cpu發生了什麼事情,cpu就要停止目前的工作來處理這個中斷。比如當網卡收到包時,假如cpu正在執行某個應用進程處理程序,此刻就會被網卡中斷所打斷執行中斷處理程序。每個外設對應的中斷處理程序自然是不同的,因此爲了進行區分,防止多個設備發出相同的中斷請求,系統中的每個設備都被分配了一個獨一無二的IRQ(Interupt Request)

每個設備對應的IRQ信息可以從/proc/interrupts中讀取:

第一列即爲每臺設備對應的IRQ,這個在不同機器上可能會不同,該圖中我們可以看出網卡eth1對應的IRQ16

第二列到第五列分別對應cpu0-cpu3已經處理的關於某個IRQ(對應某設備)的中斷數量。這是我做過優化之後的截圖,可以看到各個cpu都處理了大概一樣多的eth1網卡中斷。

第六列對應中斷控制器。

第七列就是具體的設備了。

其實我們的優化方法也就是想把eth1的中斷請求平均分配在各個cpu上,從linux 2.4開始就實現了把IRQ綁定在某個cpu或者某些cpu上,叫做多cpu中斷親和性。要實現這一點,有若干條件:

1. eth1對應的中斷控制器必須是IO-APIC芯片,有時候是硬件上支持,但IO-APIC未被啓用,需要調整系統啓動參數來更改,這一點一定要注意。

2. 只有特定CPU才支持,如果是那種CPU超線程的,沒有辦法,目前我實驗過的一些INTEL至強處理器是支持的,如Intel(R) Xeon(R) CPU            5130  @ 2.00GHz,AMD的試過幾個型號不支持。

設置中斷分配的方法很簡單,就是修改/proc/irq/IRQ/smp_affinity,這裏IRQ前面已經說過可以從/proc/interrupts裏面查,上圖的例子中eth1對應的IRQ16,如果我們需要把eth1網卡中斷被各個cpu平均處理,只需要執行如下命令:

echo ff > /proc/irq/16/ smp_affinity

     如果想把eth1對應的中斷綁定在cpu2上處理,執行:

      echo 04 > /proc/irq/16/ smp_affinity

  此處echo的數字爲十六進制,置1的位對應cpu生效,1對應cpu0, 2對應cpu1, 4對應cpu28對應cpu3,如此類推。

     下面看下我們優化後的效果吧:

       可以看出cpu繁忙程度平均了,單個cpu的佔用率只有20-30%了,處理能力大大提升。

   上面截圖都是在聊天記錄漫遊的幾臺機器上做的優化,優化後機器cpu負載大大降低,不需要進行擴容,有效降低了運營成本。

 

附:

1、如何察看某個進程在哪個CPU上運行:

#top

之後按下f 進入top Current Fields設置頁面:

選中:j: P          = Last used cpu (SMP)

則多了一項:P 顯示此進程使用哪個CPU。

2、Linux下,如何看每個CPU的使用率:

#top

之後按下1. 則顯示多個CPU

Cpu0  :  1.0%us,  3.0%sy,  0.0%ni, 96.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu1  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

另外,shift+p,按cpu使用率排序,shift+m,按內存使用率排序


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章