随着雲計算産業的異軍突起,網絡技術的不斷創新,越來越多的網絡裝置基礎架構逐漸向基于通用處理器平台的架構方向融合,從傳統的實體網絡到虛拟網絡,從扁平化的網絡結構到基于 SDN 分層的網絡結構,無不展現出這種創新與融合。
這在使得網絡變得更加可控制和成本更低的同時,也能夠支援大規模使用者或應用程式的性能需求,以及海量資料的處理。究其原因,其實是高性能網絡程式設計技術随着網絡架構的演進不斷突破的一種必然結果。
如今,關注的更多是 C10M 問題(即單機 1 千萬個并發連接配接問題)。很多計算機領域的大佬們從硬體上和軟體上都提出了多種解決方案。從硬體上,比如說,現在的類似很多 40Gpbs、32-cores、256G RAM 這樣配置的 X86 伺服器完全可以處理 1 千萬個以上的并發連接配接。
但是從硬體上解決問題就沒多大意思了,首先它成本高,其次不通用,最後也沒什麼挑戰,無非就是堆砌硬體而已。是以,抛開硬體不談,我們看看從軟體上該如何解決這個世界難題呢?

他提到了 UNIX 的設計初衷其實為電話網絡的控制系統而設計的,而不是一般的伺服器作業系統,是以,它僅僅是一個資料負責資料傳送的系統,沒有所謂的控制層面和資料層面的說法,不适合處理大規模的網絡資料包。最後他得出的結論是:
OS 的核心不是解決 C10M 問題的辦法,恰恰相反 OS 的核心正式導緻 C10M 問題的關鍵所在。
1、中斷處理。當網絡中大量資料包到來時,會産生頻繁的硬體中斷請求,這些硬體中斷可以打斷之前較低優先級的軟中斷或者系統調用的執行過程,如果這種打斷頻繁的話,将會産生較高的性能開銷。
2、記憶體拷貝。正常情況下,一個網絡資料包從網卡到應用程式需要經過如下的過程:資料從網卡通過 DMA 等方式傳到核心開辟的緩沖區,然後從核心空間拷貝到使用者态空間,在 Linux 核心協定棧中,這個耗時操作甚至占到了資料包整個處理流程的 57.1%。
3、上下文切換。頻繁到達的硬體中斷和軟中斷都可能随時搶占系統調用的運作,這會産生大量的上下文切換開銷。另外,在基于多線程的伺服器設計架構中,線程間的排程也會産生頻繁的上下文切換開銷,同樣,鎖競争的耗能也是一個非常嚴重的問題。
4、局部性失效。如今主流的處理器都是多個核心的,這意味着一個資料包的處理可能跨多個 CPU 核心,比如一個資料包可能中斷在 cpu0,核心态處理在 cpu1,使用者态處理在 cpu2,這樣跨多個核心,容易造成 CPU 緩存失效,造成局部性失效。如果是 NUMA 架構,更會造成跨 NUMA 通路記憶體,性能受到很大影響。
5、記憶體管理。傳統伺服器記憶體頁為 4K,為了提高記憶體的通路速度,避免 cache miss,可以增加 cache 中映射表的條目,但這又會影響 CPU 的檢索效率。
綜合以上問題,可以看出核心本身就是一個非常大的瓶頸所在。那很明顯解決方案就是想辦法繞過核心。
針對以上弊端,分别提出以下技術點進行探讨。
1、控制層和資料層分離。将資料包處理、記憶體管理、處理器排程等任務轉移到使用者空間去完成,而核心僅僅負責部分控制指令的處理。這樣就不存在上述所說的系統中斷、上下文切換、系統調用、系統排程等等問題。
2、使用多核程式設計技術代替多線程技術,并設定 CPU 的親和性,将線程和 CPU 核進行一比一綁定,減少彼此之間排程切換。
3、針對 NUMA 系統,盡量使 CPU 核使用所在 NUMA 節點的記憶體,避免跨記憶體通路。
4、使用大頁記憶體代替普通的記憶體,減少 cache-miss。
5、采用無鎖技術解決資源競争問題。
經很多前輩先驅的研究,目前業内已經出現了很多優秀的內建了上述技術方案的高性能網絡資料處理架構,如 6wind、windriver、netmap、dpdk 等,其中,Intel 的 dpdk 在衆多方案脫穎而出,一騎絕塵。
dpdk 為 Intel 處理器架構下使用者空間高效的資料包處理提供了庫函數和驅動的支援,它不同于 Linux 系統以通用性設計為目的,而是專注于網絡應用中資料包的高性能處理。
也就是 dpdk 繞過了 Linux 核心協定棧對資料包的處理過程,在使用者空間實作了一套資料平面來進行資料包的收發與處理。在核心看來,dpdk 就是一個普通的使用者态程序,它的編譯、連接配接和加載方式和普通程式沒有什麼兩樣。
相對傳統的基于核心的網絡資料處理,dpdk 對從核心層到使用者層的網絡資料流程進行了重大突破,我們先看看傳統的資料流程和 dpdk 中的網絡流程有什麼不同。
傳統 Linux 核心網絡資料流程:
dpdk 網絡資料流程:
下面就具體看看 dpdk 做了哪些突破?
UIO (使用者空間的 I/O 技術)的加持。
dpdk 能夠繞過核心協定棧,本質上是得益于 UIO 技術,通過 UIO 能夠攔截中斷,并重設中斷回調行為,進而繞過核心協定棧後續的處理流程。
UIO 裝置的實作機制其實是對使用者空間暴露檔案接口,比如當注冊一個 UIO 裝置 uioX,就會出現檔案 /dev/uioX,對該檔案的讀寫就是對裝置記憶體的讀寫。除此之外,對裝置的控制還可以通過 /sys/class/uio 下的各個檔案的讀寫來完成。
記憶體池技術
dpdk 在使用者空間實作了一套精巧的記憶體池技術,核心空間和使用者空間的記憶體互動不進行拷貝,隻做控制權轉移。這樣,當收發資料包時,就減少了記憶體拷貝的開銷。
大頁記憶體管理
dpdk 實作了一組大頁記憶體配置設定、使用和釋放的 API,上層應用可以很友善使用 API 申請使用大頁記憶體,同時也相容普通的記憶體申請。
無鎖環形隊列
dpdk 基于 Linux 核心的無鎖環形緩沖 kfifo 實作了自己的一套無鎖機制。支援單生産者入列/單消費者出列和多生産者入列/多消費者出列操作,在資料傳輸的時候,降低性能的同時還能保證資料的同步。
poll-mode網卡驅動
DPDK網卡驅動完全抛棄中斷模式,基于輪詢方式收包,避免了中斷開銷。
NUMA
dpdk 記憶體配置設定上通過 proc 提供的記憶體資訊,使 CPU 核心盡量使用靠近其所在節點的記憶體,避免了跨 NUMA 節點遠端通路記憶體的性能問題。
CPU 親和性
dpdk 利用 CPU 的親和性将一個線程或多個線程綁定到一個或多個 CPU 上,這樣線上程執行過程中,就不會被随意排程,一方面減少了線程間的頻繁切換帶來的開銷,另一方面避免了 CPU 緩存的局部失效性,增加了 CPU 緩存的命中率。
多核排程架構
dpdk 基于多核架構,一般會有主從核之分,主核負責完成各個子產品的初始化,從核負責具體的業務處理。
除了上述之外,dpdk 還有很多的技術突破,可以用下面這張圖來概之。
dpdk 作為優秀的使用者空間高性能資料包加速套件,現在已經作為一個“膠水”子產品被用在多個網絡資料處理方案中,用來提高性能。如下是衆多的應用。
OVS
Open vSwitch 是一個多核虛拟交換機平台,支援标準的管理接口和開放可擴充的可程式設計接口,支援第三方的控制接入。
<a href="https://github.com/openvswitch/ovs">https://github.com/openvswitch/ovs</a>
VPP
VPP 是 cisco 開源的一個高性能的包處理架構,提供了 交換/路由 功能,在虛拟化環境中,使它可以當做一個虛拟交換機來使用。在一個類 SDN 的處理架構中,它往往充當資料面的角色。經研究表明,VPP 性能要好于 ovs+dpdk 的組合,但它更适用于NFV,适合做特定功能的網絡子產品。
<a href="https://wiki.fd.io/view/VPP">https://wiki.fd.io/view/VPP</a>
Lagopus
Lagopus 是另一個多核虛拟交換的實作,功能和 OVS 差不多,支援多種網絡協定,如 Ethernet,VLAN,QinQ,MAC-in-MAC,MPLS 和 PBB,以及隧道協定,如 GRE,VxLan 和 GTP。
<a href="https://github.com/lagopus/lagopus/blob/master/QUICKSTART.md">https://github.com/lagopus/lagopus/blob/master/QUICKSTART.md</a>
Snabb
Snabb 是一個簡單且快速的資料包處理工具箱。
<a href="https://github.com/SnabbCo/snabbswitch/blob/master/README.md">https://github.com/SnabbCo/snabbswitch/blob/master/README.md</a>
OPENCONTRAIL
一個內建了 SDN 控制器的虛拟路由器,現在多用在 OpenStack 中,結合 Neutron 為 OpenStack 提供一站式的網絡支援。
<a href="http://www.opencontrail.org/">http://www.opencontrail.org/</a>
CloudRouter
一個分布式的路由器。
<a href="https://cloudrouter.org/">https://cloudrouter.org/</a>
mTCP
mTCP 是一個針對多核系統的高可擴充性的使用者空間 TCP/IP 協定棧。
<a href="https://github.com/eunyoung14/mtcp/blob/master/README">https://github.com/eunyoung14/mtcp/blob/master/README</a>
IwIP
IwIP 針對 RAM 平台的精簡版的 TCP/IP 協定棧實作。
<a href="http://git.savannah.gnu.org/cgit/lwip.git/tree/README">http://git.savannah.gnu.org/cgit/lwip.git/tree/README</a>
Seastar
Seastar 是一個開源的,基于 C++ 11/14 feature,支援高并發和低延遲的異步程式設計高性能庫。
<a href="http://www.seastar-project.org/">http://www.seastar-project.org/</a>
f-stack
騰訊開源的使用者空間協定棧,移植于 FreeBSD協定棧,粘合了 POSIX API,上層應用(協程架構,Nginx,Redis),純 C 編寫,易上手。
<a href="https://github.com/f-stack/f-stack">https://github.com/f-stack/f-stack</a>
dpdk 繞過了 Linux 核心協定棧,加速資料的處理,使用者可以在使用者空間定制協定棧,滿足自己的應用需求,目前出現了很多基于 dpdk 的高性能網絡架構,OVS 和 VPP 是常用的資料面架構,mTCP 和 f-stack 是常用的使用者态協定棧。很多大公司都在使用 dpdk 來優化網絡性能。
PS:對雲計算感興趣的小夥伴可以關注我的微信公衆号:aCloudDeveloper,專注雲計算領域,堅持分享幹貨。
stay hungry
stay foolish
----jobs
希望多多燒香!