1. 程式人生 > 其它 >C10K C10M 通過DPDK+使用者態協議棧來進行核心旁路來提升網路效能

C10K C10M 通過DPDK+使用者態協議棧來進行核心旁路來提升網路效能

千萬併發連線下,如何保障網路效能? https://mp.weixin.qq.com/s/lDhCoLN0mknquJcO15Fd2Q

千萬併發連線下,如何保障網路效能?

過去幾十年網際網路呈爆發式的增長,內容的豐富以及層出不窮的DDoS攻擊等,對網路效能提出了極大的挑戰,也同樣促進了網路基礎設施的快速發展。運營商的頻寬越來越大,CPU/網絡卡等硬體的效能也會越來越強。但在很長時間內,軟體的效能提升落後於硬體的效能提升,並嚴重限制了應用程式的效能,大部分時間不得不依靠堆機器來應對,造成了大量的資源浪費和成本提高。

隨著軟體的不斷髮展,在新世紀的第一個10年時,通過多執行緒和事件驅動(kqueue/epoll等)解決了C10K的問題

。但是在第二個10年卻不堪重負,亟需新的解決方案來應對網路流量的增長。

比如騰訊雲對外提供的HttpDNS服務每隔幾個月請求量都會翻倍,對高效能的網路處理和使用者態協議棧都有強烈的需求。HttpDNS早期使用的核心協議棧只能做到單機不到10萬QPS的TCP短連線服務。隨著技術的進步和發展,如REUSEPORT等,後續核心協議棧也可以做到幾十萬QPS了,但依然存在非常大的橫向擴充套件瓶頸。基於這樣的瓶頸下,騰訊雲迫切需要一個高效能的網路服務框架,所以選擇了通過DPDK+使用者態協議棧來進行核心旁路來提升網路效能

Robert David Graham在2013年針對C10M的演講中,對於如何達到千萬併發連線,最主要的觀點就是核心才是阻礙效能提升的問題

,我們應該繞過核心(kernel by pass,核心旁路)以及大量其它的技術優化,如輪詢、零拷貝、Hugepage等。

Linux核心後續引入的eBPF和XDP同樣能夠大幅提升網路效能,但是其提升效能的本質依然是繞過核心,目前還未能對Intel DPDK生態造成實質的衝擊,尤其是對高核心版本和網絡卡驅動的依賴,嚴重限制了在企業的使用推廣。

在此次演講之前,相關的技術已經得到了一定的應用,如演講中提到的PF_RING、Netmap、IntelDPDK等資料驅動,騰訊雲DNSPod在2012年就已經完成了相關軟硬體的調研選型工作,並最終選擇DPDK(此時尚未開源)實現了新一代的權威DNS伺服器達到了單10GE 1100萬QPS的效能,大幅提升了DNS的常規解析和抗攻擊能力。但是確實直到該演講出現後,相關技術才在業界得到了大規模的開發應用,尤其是從中脫穎而出的DPDK,幾乎成了高效能網路程式的標配。而我們也是在16年的時候將權威DNS中使用DPDK的網路模組單獨抽出來作為一個獨立的通用的網路框架

,可以複用到多個業務上提升網路效能,也就是現在的F-Stack。

一、F-Stack介紹及技術特點

F-Stack是一個全使用者態的高效能的網路接入開發包,基於DPDK、FreeBSD協議棧、微執行緒介面等,使用者只需要關注業務邏輯,簡單的接入F-Stack即可實現高效能的網路伺服器。將網路包進行核心旁路到應用層進行處理雖然大幅提升了網路效能,但是也無法再使用核心的網路協議棧了,這對4層以下以及簡單的UDP 7層應用影響不大,但是對其他的7層應用來說,一個成熟的使用者態協議棧是必須的,所以F-Stack就是騰訊雲DNSPod給出的方案。

F-Stack是基本完整的網路程式設計框架,相當於用膠水粘合了了DPDK網路I/O模組、FreeBSD使用者態協議棧、POSIX Like API,非同步程式設計介面、部分上層應用等,供使用者接入使用

使用純C開發(部分第三方元件使用了C++、F-Stack進行了封裝),容易上手,但也要求使用者有一定的DPDK使用基礎。使用BSD 2-Clause開源協議,對商業使用非常友好。那對於F-Stack都有哪些技術特點呢?接下來將繼續介紹。

(一)多程序架構,輪詢模式

這裡是F-Stack的一個基本架構,採用多程序模型,全使用者態,每個程序與一個CPU核心、網絡卡收發佇列進行繫結,擁有更好的記憶體區域性性,避免快取失效,且程序內部使用輪詢模式,無鎖、無排程、無上下文切換。

F-Stack目前採用多程序架構,各程序擁有自己程序獨立的協議棧,應用介面和應用層業務邏輯,規避了核心的多種效能瓶頸,各個程序間無資料共享,有非常好的橫向擴充套件能力。

(二)DPDK開發套件

DPDK是廣泛使用的資料平面開發套件,此處不再對其本身進行過多介紹。F-Stack對DPDK版本的選用上除了初始開源版本使用了16.07版本之外,很快升級並一直保持使用DPDK的LTS版本(xx.11)版本,但一般會在最新的LTS版本釋出之後數個月在dev分支進行升級支援,並在更晚之後的時間(一般1年左右)正式釋出,如目前F-Stack主力穩定的1.20和1.21版本分別使用了DPDK 18.11.x和19.11.x版本,在開發分支中則支援了20.11.x版本。

(三)FreeBSD協議棧

F-Stack對於選用FreeBSD協議棧進行使用者態移植,背後其實是有過很多的思考和嘗試的,此處僅列覺幾個FreeBSD協議棧的優點,更多資訊可以通過後面的F-Stack背景故事進行了解。

  • 協議棧功能完善,且有大量工具可以對網路進行除錯分析,如sysctl、ifconfig、netstat、netgraph、ipfw、ndp等。

  • 可以跟進社群的改進,無需自己開發維護,有原始使用者態移植可供參考,大幅減少工作量,見libplebnet和libuinet。

  • 相比Linux的協議棧實現複雜,FreeBSD的程式碼更清晰易懂;Linux遵循GPL協議開源,可能會限制部分使用者的使用。

F-Stack目前釋出版本均基於FreeBSD releng 11.0 版本,並移植了部分後續版本的patch,功能完善但也冗餘(去除了部分模組未編譯進F-Stack,如SCTP、IPSEC等),除錯分析工具完善,執行穩定。後續則會升級到 FreeBSD releng 13.0版本,並將持續跟進社群的重大改進。

(四)POSIX相容介面

F-Stack提供POSIX like介面,字首為“ff_”,如“ff_socket”“ff_bind”等,並提供了“ff_kqueue”事件驅動介面並同時基於kqueue封裝了“ff_epoll”介面,除“ff_epoll”介面的使用上與linux系統介面略有區別外,其他介面用法完全相容,現有程式可以做到簡單改動即可接入。

需要注意的是,雖然介面用法完全相容,但是因為很多標記位在Linux和FreeBSD系統的定義並不相同,F-Stack介面內部會進行定義的轉換,但是並不能保證100%支援,尤其是後續新增的標記定義,也需要持續進行更新維護。

POSIX like介面對原有應用的移植是友好的,並且使用上也比較安全,但是因為涉及到記憶體拷貝,所以效能上並不能達到最優,後續F-Stack也會提供一套獨立的零拷貝API供有需要的使用者選用。

(五)微執行緒框架

F-Stack應用程式必須使用非同步模式介面進行程式設計,但也同時提供了微執行緒(協程)框架,可以供使用者進行同步程式設計,非同步執行。

微執行緒框架使用了同為騰訊開源的MSEC中的一部分micro_thread,需要特別注意的是微執行緒模組的開源協議是GPL-2.0,並不是F-Stack主要的必須核心模組,對F-Stack主體開源協議並無影響,但是如果使用者以 micro_thread模組進行應用開發,則需關注開源協議可能造成的影響。

(六)應用移植

F-Stack目前是提供lib庫接入的方式,需要與業務應用程式一起編譯打包,並直接提供了已經移植好的Nginx和Redis應用供使用者直接使用。

對於部分原多執行緒架構的應用程式,尤其是有資源共享時,為了達到更好的效能和橫向擴充套件能力,我們的建議是儘量能夠拆分並減少資源的共享。如果實在無法拆分,F-Stack後續也會考慮提供獨立的網路I/O和協議棧模組,但是效能的下降也將不可避免。

(七)適用場景

這裡我們先來看下Nginx分別使用F-Stack和核心協議棧的一個性能對比,分別是短連結和長連結,需要說明的是核心協議棧也是經過了多種調優之後的測試資料,比如網絡卡佇列、worker的CPU親和性繫結,開啟REUSEPORT 和其他核心網路引數的優化調整。

這裡F-Stack對核心協議棧都有明顯的提升,但是其中超過12核之後的短連結的提升尤其明顯,F-Stack對大部分高併發的網路應用場景都有較好的效能優化和使用價值,其中最適合的是超大併發的TCP短連結業務場景,這也是我們HttpDNS的主要業務場景。

當然,想要全面的瞭解F-Stack的業務應用,就必須要從其發展歷史的開啟來看待。

(八)F-Stack發展歷史

目前對外開源的F-Stack已經是3.0版本,1.0版本是12-13年DNSPod的權威DNS選用DPDK來提升效能時候,是一個簡易的使用者態TCP協議棧用來支援TCP DNS,13年上線後一直在線上持續執行,近兩年已經全部升級到3.0了。

為了支援DNS業務的快速發展,不能缺少一個高效能的使用者態協議棧,而維護一個功能完善的TCP協議棧需要耗費大量的精力,這也是開發F-Stack 2.0和3.0的一個很重要的原因。

16年的時候當時的leader拍板下,我們放棄了繼續維護1.0的協議棧,選用開源協議棧進行適配升級並對外開源,通過調研先選擇了seastar(排除了MTCP、LwIP等),並在當年做了2.0版本,也做了一些應用適配,比如 HttpDNS,騰訊雲動態加速CDN(DSA,現在已經合併到全站加速ECDN中)等,但是理想是美好的,現實是殘酷的,雖然基於F-Stack2.0版本的HttpDNS在實驗室表現堪稱完美,效能優異,可擴充套件外掛式架構等,但是在現網少量灰度運營時踩了無數坑,這和Seastar本身的使用場景是相關的,作為 ScyllaDB的元件,其主要應用場景是在內網的,並不能很好的適應外網複雜的網路環境。

在團隊填了不少坑,也提交了多個Pull Request到Seastar後我們發現又陷入了1.0版本的迴圈,所以堅持一段時間後還是放棄了Seastar,轉而從更成熟的Llinux和FreeBSD協議棧中選擇了FreeBSD來開發F-Stack 3.0,也就是目前對外開源的版本。當然F-Stack 2.0的框架其實也並沒有完全廢棄,雖然在主要服務於外網的HttpDNS上水土不服,但是在以內網互聯加速為主要場景的CDN動態加速DSA中是運行了多年才進行升級的。

17年上半年我們基於DPDK和FreeBSD協議棧開發完成了F-Stack 3.0,並對外開源,並很快重新適配了HttpDNS,因為HttpDNS的請求量一直在快速增長,業務效能壓力非常大,所以優先適配HttpDNS,並逐步上線對外提供服務,雖然後續也遇到了一些問題,但是都很快優化並穩定下來,到目前支撐了日請求量萬億的HttpDNS請求並保持了10倍。

(九)F-Stack開源版本歷史

  • 2017.4.14 正式開源

  • 2017.11.27 Release 1.11

  • 2018.5.21 Release 1.12

  • 2019.11.15 Release1.13

  • 2019.11.23 Release 1.20

  • 2021.1.29 Release 1.21

二、F-StackROADMAP

目前F-Stack也一直在持續維護中,預計2021年底至2022年初將釋出1.22版本,可能包含以下新特性:

  • DPDK 20.11,dev分支已經升級支援,相比19.11之前在編譯和使用方式上有很大區別,僅支援使用meson/ninja進行編譯。

  • FreeBSD 13.0,dev分支已經升級支援,但是目前尚未完全穩定,依然存在一些問題,如BBR/RACK尚不能正常工作,多程序效能存在部分問題待優化,部分工具的部分功能異常(如ff_netstat對監聽埠的檢視等),還需進一步除錯優化。

  • 新的零拷貝介面支援。

  • 原有應用一鍵移植支援,提供的獨立的網路I/O和協議棧模組,提供類似LD_PRELOAD或其他方式簡化應用移植門檻,但一定會導致效能下降。

  • Nginx-1.20支援。

  • Redis 6支援。

接收端網絡卡分流的預設方式由RSS修改為Flow Director,但依然保持現有預設的RSS策略。

【注意】以上功能會視具體時間安排調整,部分功能將很可能無法包含在1.22版本中釋出,將會順延至後續版本進行支援。

三、F-Stack實踐案例

F-Stack自從開源後獲得了全球大量研究機構、高校、公司的肯定,用於進行技術研究工作或線上商業化專案,那在這裡會給大家僅列舉F-Stack使用者實際現網業務的實踐案例。

(一)騰訊雲HttpDNS

HttpDNS服務主要用於移動端APP,解決其預設DNS大量存在的解析失敗,解析結果跨網,解析劫持等問題,目前各大TOP APP大部分都有使用此類技術,而騰訊雲DNSPod作為最早推出商用HttpDNS服務,目前服務大量使用者,日請求量萬億級,歷史版本介紹可參考公眾號“鵝廠網事”上的文章千億級HttpDNS服務是怎樣煉成的,當然目前最新的HttpDNS 也已經迭代更新了多個版本,新的專業版支援了更多的特性功能,如IPv6,DNSPod權威資料推送,使用者自定義域名解析,危險域名攔截(使用者自定義是否開啟及攔截哪些類別的危險域名),黑白名單,請求統計等一系列功能,也都構建在 F-Stack基礎架構之上。

(二)DNSPod權威DNS

作為F-Stack的父專案,DNSPod權威DNS為近千萬域名提供權威解析服務,受益於F-Stack的高效能網路服務,最新版本的權威DNS已經在百G機型上達到了單機1億QPS的效能,具體見本人之前的一篇文章《基於F-Stack 的權威DNS單機1億QPS效能優化實踐》,目前DNSPod總線上容量達到了數十億QPS,結合騰訊集團遍佈全球的大頻寬節點部署和先進的防護裝置及演算法,DNSPod在客戶無感知情況下多次成功防護TB級以上的DDoS攻擊,最近一次發生在2021.8.27週五下午,多種攻擊方式混合攻擊,平臺受攻擊合計峰值超過5T。

四、其它使用者態協議棧介紹

  • VPP

VPP(https://fd.io/)由思科主導,多個大廠參與,其使用者態協議棧Host Stack由思科交換機協議棧發展而來,開源時間晚於F-Stack,但是是目前社群活躍度最高的使用者態協議棧。

  • MTCP

MTCP(http://shader.kaist.edu/mtcp/)Stack來自韓國KAIST,在業界也有廣泛的使用,主要問題是如其名字所示僅支援TCP。

  • Seastar

Seastar(https://github.com/scylladb/seastar)作為ScyllaDB的子專案,其Native stack在內網有較好的表現,內網場景使用較多。

  • LwIP

LwIP(http://savannah.nongnu.org/projects/lwip/)來自瑞典電腦科學院,輕量級協議棧,主要用於嵌入式系統等,但也有不少廠商基於LwIP進行修改移植支援自己的應用。

C10K