nux平台上的C10M問題

2021-06-25 09:06:25 字數 1861 閱讀 2880

對於做大量併發伺服器端(比如web伺服器nginx、apache等)開發的童鞋,肯定知道有乙個名為c10k的問題。當然,這是乙個比較古老的問題了,從03年(非準確值)提及到現在已經有10餘年之久。而隨著整個網路相關技術的高速發展,包括cpu、網絡卡、作業系統等,人們對業務需求所追求的併發連線效能也從10k提公升到10m級別,即所謂的c10m問題。這個問題的初次提及到現在應該還沒多久,大概也就是2023年

相比以前,現在的硬體很便宜,1200美元可以買一台8核cpu、64gb和帶有固態硬碟以及10g萬兆網絡卡的通用電腦。這種通用電腦的效能很高,足夠充當各種網路服務裝置,因此很多看似貼有伺服器專用標籤的網路裝置,揭開標籤紙之後,就是一台普普通通的個人通用電腦。

硬體不是10m問題的效能瓶頸所在處,真正的問題出在軟體上,尤其是*nux作業系統。這裡有幾點:

首先,最初的設計是讓unix成為乙個**網路的控制系統,而不是成為乙個伺服器作業系統。對於控制系統而言,針對的主要目標是使用者和任務,而並沒有針對作為協助功能的資料處理做特別設計,也就是既沒有所謂的快速路徑、慢速路徑,也沒有各種資料服務處理的優先順序差別。

其次,傳統的cpu,因為只有乙個核,作業系統**以多執行緒或多工的形式來提公升整體效能。而現在,4核、8核、32核、64核和100核,都已經是真實存在的cpu晶元,如何提高多核的效能可擴充套件性,是乙個必須面對的問題。比如讓同一任務分割在多個核心上執行,以避免cpu的空閒浪費,當然,這裡面要解決的技術點有任務分割、任務同步和非同步等。

再次,核心快取大小與記憶體速度是乙個關鍵問題。現在,記憶體已經變得非常的便宜,隨便一台普通的膝上型電腦,記憶體至少也就是4g以上,高階伺服器的記憶體上24g那是相當的平常。但是,記憶體的訪問速度仍然很慢,cpu訪問一次記憶體需要約60~100納秒,相比很久以前的記憶體訪問速度,這基本沒有增長多少。對於在乙個帶有1ghz主頻cpu的電腦硬體裡,如果要實現10m效能,那麼平均每乙個包只有100納秒,如果存在兩次cpu訪問記憶體,那麼10m效能就達不到了。核心快取,也就是cpu l1/l2/ll cache,雖然訪問速度會快些,但大小仍然不夠,我之前接觸到的高階至強,llc容量大小貌似也就是12m。

解決這些問題的關鍵在於如何將功能邏輯做好恰當的劃分,比如專門負責控制邏輯的控制面和專門負責資料邏輯的資料面。資料面專門負責資料的處理,屬於資源消耗的主要因素,壓力巨大,而相比如此,控制麵只負責一些偶爾才有非業務邏輯,比如與外部使用者的互動、資訊的統計等等。我之前接觸過幾種網路資料處理框架,比如dpdk、6wind、windriver,它們都針對linux系統做了特別的補充設計,增加了資料面、快速路徑等等特性,其效能的提公升自然是相當巨大。

看一下這些框架的共同特點:

1,資料報直接傳遞到業務邏輯,而不是經過linux核心協議棧。這是很明顯的事情,因為我們知道,linux協議棧是複雜和繁瑣的,資料報經過它無非會導致效能的巨大下降,並且會占用大量的記憶體資源,之前有同事測試過,linux核心要吃掉2.5kb記憶體/socket。我研究過很長一段時間的dpdk

原始碼,其提供的82576和82599網絡卡驅動就直接執行在應用層,將接管網絡卡收到的資料報直接傳遞到應用層的業務邏輯裡進行處理,而無需經過linux核心協議棧。當然,發往本伺服器的非業務邏輯資料報還是要經過linux核心協議棧的,比如使用者的ssh遠端登入操作連線等。

2,多執行緒的核間繫結。乙個具有8核心的裝置,一般會有1個控制面執行緒和7個或8個資料面執行緒,每乙個執行緒繫結到乙個處理核心(其中可能會存在乙個控制面執行緒和乙個資料面執行緒都繫結到同乙個處理核心的情況)。這樣做的好處是最大化核心cache利用、實現無鎖設計、避免程序切換消耗等等

3,記憶體是另外乙個核心要素,常見的記憶體池設計必須在這裡得以切實應用。有幾個考慮點,首先,可以在linux系統啟動時把業務所需記憶體直接預留出來,脫離linux核心的管理。第二,linux一般採用4k每頁,而我們可以採用更大記憶體分頁,比如2m,這樣能在一定程度上減少位址轉換等的效能消耗。

完全參考:

1,2,

nux平台上的C10M問題

對於做大量併發伺服器端 比如web伺服器nginx apache等 開發的童鞋,肯定知道有乙個名為c10k的問題。當然,這是乙個比較古老的問題了,從03年 非準確值 提及到現在已經有10餘年之久。而隨著整個網路相關技術的高速發展,包括cpu 網絡卡 作業系統等,人們對業務需求所追求的併發連線效能也從...

解決在嵌入式平台上無法進行字元編碼的問題

採用 libiconv 字元編碼庫,它包含了幾乎所有的各種字符集,可以不依賴 linux 平台的字符集作為單獨乙個動態庫存在!libiconv 1.9.1 字元編碼轉換庫編譯方法 x86 platform 1 make distclean 2 configure 3 make arca ixp425...

Linux平台上C語言實現非同步佇列的兩種方法

linux上目前有兩種事件通知方式,一種是執行緒條件變數,一種是利用eventfd實現事件通知,下面介紹一下利用這兩種方法實現非同步佇列的方法。相關函式介紹 喚醒丟失問題 如果執行緒未持有與條件相關聯的互斥鎖,則呼叫 pthread cond signal 或 pthread cond broadc...