千萬并發(fā)連接下,如何保障網絡性能?


過去幾十年互聯(lián)網呈爆發(fā)式的增長,內容的豐富以及層出不窮的DDoS攻擊等,對網絡性能提出了極大的挑戰(zhàn),也同樣促進了網絡基礎設施的快速發(fā)展。運營商的帶寬越來越大,CPU/網卡等硬件的性能也會越來越強。但在很長時間內,軟件的性能提升落后于硬件的性能提升,并嚴重限制了應用程序的性能,大部分時間不得不依靠堆機器來應對,造成了大量的資源浪費和成本提高。
隨著軟件的不斷發(fā)展,在新世紀的第一個10年時,通過多線程和事件驅動(kqueue/epoll等)解決了C10K的問題。但是在第二個10年卻不堪重負,亟需新的解決方案來應對網絡流量的增長。
比如騰訊云對外提供的HttpDNS服務每隔幾個月請求量都會翻倍,對高性能的網絡處理和用戶態(tài)協(xié)議棧都有強烈的需求。HttpDNS早期使用的內核協(xié)議棧只能做到單機不到10萬QPS的TCP短連接服務。隨著技術的進步和發(fā)展,如REUSEPORT等,后續(xù)內核協(xié)議棧也可以做到幾十萬QPS了,但依然存在非常大的橫向擴展瓶頸。基于這樣的瓶頸下,騰訊云迫切需要一個高性能的網絡服務框架,所以選擇了通過DPDK+用戶態(tài)協(xié)議棧來進行內核旁路來提升網絡性能。
Robert David Graham在2013年針對C10M的演講中,對于如何達到千萬并發(fā)連接,最主要的觀點就是內核才是阻礙性能提升的問題,我們應該繞過內核(kernel by pass,內核旁路)以及大量其它的技術優(yōu)化,如輪詢、零拷貝、Hugepage等。
Linux內核后續(xù)引入的eBPF和XDP同樣能夠大幅提升網絡性能,但是其提升性能的本質依然是繞過內核,目前還未能對Intel DPDK生態(tài)造成實質的沖擊,尤其是對高內核版本和網卡驅動的依賴,嚴重限制了在企業(yè)的使用推廣。
在此次演講之前,相關的技術已經得到了一定的應用,如演講中提到的PF_RING、Netmap、IntelDPDK等數據驅動,騰訊云DNSPod在2012年就已經完成了相關軟硬件的調研選型工作,并最終選擇DPDK(此時尚未開源)實現了新一代的權威DNS服務器達到了單10GE 1100萬QPS的性能,大幅提升了DNS的常規(guī)解析和抗攻擊能力。但是確實直到該演講出現后,相關技術才在業(yè)界得到了大規(guī)模的開發(fā)應用,尤其是從中脫穎而出的DPDK,幾乎成了高性能網絡程序的標配。而我們也是在16年的時候將權威DNS中使用DPDK的網絡模塊單獨抽出來作為一個獨立的通用的網絡框架,可以復用到多個業(yè)務上提升網絡性能,也就是現在的F-Stack。
一、F-Stack介紹及技術特點
F-Stack是一個全用戶態(tài)的高性能的網絡接入開發(fā)包,基于DPDK、FreeBSD協(xié)議棧、微線程接口等,用戶只需要關注業(yè)務邏輯,簡單的接入F-Stack即可實現高性能的網絡服務器。將網絡包進行內核旁路到應用層進行處理雖然大幅提升了網絡性能,但是也無法再使用內核的網絡協(xié)議棧了,這對4層以下以及簡單的UDP 7層應用影響不大,但是對其他的7層應用來說,一個成熟的用戶態(tài)協(xié)議棧是必須的,所以F-Stack就是騰訊云DNSPod給出的方案。
F-Stack是基本完整的網絡編程框架,相當于用膠水粘合了了DPDK網絡I/O模塊、FreeBSD用戶態(tài)協(xié)議棧、POSIX Like API,異步編程接口、部分上層應用等,供用戶接入使用。
使用純C開發(fā)(部分第三方組件使用了C++、F-Stack進行了封裝),容易上手,但也要求用戶有一定的DPDK使用基礎。使用BSD 2-Clause開源協(xié)議,對商業(yè)使用非常友好。那對于F-Stack都有哪些技術特點呢?接下來將繼續(xù)介紹。
(一)多進程架構,輪詢模式
這里是F-Stack的一個基本架構,采用多進程模型,全用戶態(tài),每個進程與一個CPU核心、網卡收發(fā)隊列進行綁定,擁有更好的內存局部性,避免緩存失效,且進程內部使用輪詢模式,無鎖、無調度、無上下文切換。

F-Stack目前采用多進程架構,各進程擁有自己進程獨立的協(xié)議棧,應用接口和應用層業(yè)務邏輯,規(guī)避了內核的多種性能瓶頸,各個進程間無數據共享,有非常好的橫向擴展能力。
(二)DPDK開發(fā)套件
DPDK是廣泛使用的數據平面開發(fā)套件,此處不再對其本身進行過多介紹。F-Stack對DPDK版本的選用上除了初始開源版本使用了16.07版本之外,很快升級并一直保持使用DPDK的LTS版本(xx.11)版本,但一般會在最新的LTS版本發(fā)布之后數個月在dev分支進行升級支持,并在更晚之后的時間(一般1年左右)正式發(fā)布,如目前F-Stack主力穩(wěn)定的1.20和1.21版本分別使用了DPDK 18.11.x和19.11.x版本,在開發(fā)分支中則支持了20.11.x版本。
(三)FreeBSD協(xié)議棧
F-Stack對于選用FreeBSD協(xié)議棧進行用戶態(tài)移植,背后其實是有過很多的思考和嘗試的,此處僅列覺幾個FreeBSD協(xié)議棧的優(yōu)點,更多信息可以通過后面的F-Stack背景故事進行了解。
協(xié)議棧功能完善,且有大量工具可以對網絡進行調試分析,如sysctl、ifconfig、netstat、netgraph、ipfw、ndp等。
可以跟進社區(qū)的改進,無需自己開發(fā)維護,有原始用戶態(tài)移植可供參考,大幅減少工作量,見libplebnet和libuinet。
相比Linux的協(xié)議棧實現復雜,FreeBSD的代碼更清晰易懂;Linux遵循GPL協(xié)議開源,可能會限制部分用戶的使用。
F-Stack目前發(fā)布版本均基于FreeBSD releng 11.0 版本,并移植了部分后續(xù)版本的patch,功能完善但也冗余(去除了部分模塊未編譯進F-Stack,如SCTP、IPSEC等),調試分析工具完善,運行穩(wěn)定。后續(xù)則會升級到 FreeBSD releng 13.0版本,并將持續(xù)跟進社區(qū)的重大改進。
(四)POSIX兼容接口
F-Stack提供POSIX like接口,前綴為“ff_”,如“ff_socket”“ff_bind”等,并提供了“ff_kqueue”事件驅動接口并同時基于kqueue封裝了“ff_epoll”接口,除“ff_epoll”接口的使用上與linux系統(tǒng)接口略有區(qū)別外,其他接口用法完全兼容,現有程序可以做到簡單改動即可接入。
需要注意的是,雖然接口用法完全兼容,但是因為很多標記位在Linux和FreeBSD系統(tǒng)的定義并不相同,F-Stack接口內部會進行定義的轉換,但是并不能保證100%支持,尤其是后續(xù)新增的標記定義,也需要持續(xù)進行更新維護。
POSIX like接口對原有應用的移植是友好的,并且使用上也比較安全,但是因為涉及到內存拷貝,所以性能上并不能達到最優(yōu),后續(xù)F-Stack也會提供一套獨立的零拷貝API供有需要的用戶選用。
(五)微線程框架
F-Stack應用程序必須使用異步模式接口進行編程,但也同時提供了微線程(協(xié)程)框架,可以供用戶進行同步編程,異步執(zhí)行。
微線程框架使用了同為騰訊開源的MSEC中的一部分micro_thread,需要特別注意的是微線程模塊的開源協(xié)議是GPL-2.0,并不是F-Stack主要的必須核心模塊,對F-Stack主體開源協(xié)議并無影響,但是如果用戶以 micro_thread模塊進行應用開發(fā),則需關注開源協(xié)議可能造成的影響。
(六)應用移植
F-Stack目前是提供lib庫接入的方式,需要與業(yè)務應用程序一起編譯打包,并直接提供了已經移植好的Nginx和Redis應用供用戶直接使用。
對于部分原多線程架構的應用程序,尤其是有資源共享時,為了達到更好的性能和橫向擴展能力,我們的建議是盡量能夠拆分并減少資源的共享。如果實在無法拆分,F-Stack后續(xù)也會考慮提供獨立的網絡I/O和協(xié)議棧模塊,但是性能的下降也將不可避免。
(七)適用場景
這里我們先來看下Nginx分別使用F-Stack和內核協(xié)議棧的一個性能對比,分別是短鏈接和長鏈接,需要說明的是內核協(xié)議棧也是經過了多種調優(yōu)之后的測試數據,比如網卡隊列、worker的CPU親和性綁定,開啟REUSEPORT 和其他內核網絡參數的優(yōu)化調整。


這里F-Stack對內核協(xié)議棧都有明顯的提升,但是其中超過12核之后的短鏈接的提升尤其明顯,F-Stack對大部分高并發(fā)的網絡應用場景都有較好的性能優(yōu)化和使用價值,其中最適合的是超大并發(fā)的TCP短鏈接業(yè)務場景,這也是我們HttpDNS的主要業(yè)務場景。
當然,想要全面的了解F-Stack的業(yè)務應用,就必須要從其發(fā)展歷史的開啟來看待。
(八)F-Stack發(fā)展歷史
目前對外開源的F-Stack已經是3.0版本,1.0版本是12-13年DNSPod的權威DNS選用DPDK來提升性能時候,是一個簡易的用戶態(tài)TCP協(xié)議棧用來支持TCP DNS,13年上線后一直在線上持續(xù)運行,近兩年已經全部升級到3.0了。
為了支持DNS業(yè)務的快速發(fā)展,不能缺少一個高性能的用戶態(tài)協(xié)議棧,而維護一個功能完善的TCP協(xié)議棧需要耗費大量的精力,這也是開發(fā)F-Stack 2.0和3.0的一個很重要的原因。
16年的時候當時的leader拍板下,我們放棄了繼續(xù)維護1.0的協(xié)議棧,選用開源協(xié)議棧進行適配升級并對外開源,通過調研先選擇了seastar(排除了MTCP、LwIP等),并在當年做了2.0版本,也做了一些應用適配,比如 HttpDNS,騰訊云動態(tài)加速CDN(DSA,現在已經合并到全站加速ECDN中)等,但是理想是美好的,現實是殘酷的,雖然基于F-Stack2.0版本的HttpDNS在實驗室表現堪稱完美,性能優(yōu)異,可擴展插件式架構等,但是在現網少量灰度運營時踩了無數坑,這和Seastar本身的使用場景是相關的,作為 ScyllaDB的組件,其主要應用場景是在內網的,并不能很好的適應外網復雜的網絡環(huán)境。
在團隊填了不少坑,也提交了多個Pull Request到Seastar后我們發(fā)現又陷入了1.0版本的循環(huán),所以堅持一段時間后還是放棄了Seastar,轉而從更成熟的Llinux和FreeBSD協(xié)議棧中選擇了FreeBSD來開發(fā)F-Stack 3.0,也就是目前對外開源的版本。當然F-Stack 2.0的框架其實也并沒有完全廢棄,雖然在主要服務于外網的HttpDNS上水土不服,但是在以內網互聯(lián)加速為主要場景的CDN動態(tài)加速DSA中是運行了多年才進行升級的。
17年上半年我們基于DPDK和FreeBSD協(xié)議棧開發(fā)完成了F-Stack 3.0,并對外開源,并很快重新適配了HttpDNS,因為HttpDNS的請求量一直在快速增長,業(yè)務性能壓力非常大,所以優(yōu)先適配HttpDNS,并逐步上線對外提供服務,雖然后續(xù)也遇到了一些問題,但是都很快優(yōu)化并穩(wěn)定下來,到目前支撐了日請求量萬億的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-Stack?ROADMAP
目前F-Stack也一直在持續(xù)維護中,預計2021年底至2022年初將發(fā)布1.22版本,可能包含以下新特性:
DPDK 20.11,dev分支已經升級支持,相比19.11之前在編譯和使用方式上有很大區(qū)別,僅支持使用meson/ninja進行編譯。
FreeBSD 13.0,dev分支已經升級支持,但是目前尚未完全穩(wěn)定,依然存在一些問題,如BBR/RACK尚不能正常工作,多進程性能存在部分問題待優(yōu)化,部分工具的部分功能異常(如ff_netstat對監(jiān)聽端口的查看等),還需進一步調試優(yōu)化。
新的零拷貝接口支持。
原有應用一鍵移植支持,提供的獨立的網絡I/O和協(xié)議棧模塊,提供類似LD_PRELOAD或其他方式簡化應用移植門檻,但一定會導致性能下降。
Nginx-1.20支持。
Redis 6支持。
接收端網卡分流的默認方式由RSS修改為Flow Director,但依然保持現有默認的RSS策略。
【注意】以上功能會視具體時間安排調整,部分功能將很可能無法包含在1.22版本中發(fā)布,將會順延至后續(xù)版本進行支持。
三、F-Stack實踐案例
F-Stack自從開源后獲得了全球大量研究機構、高校、公司的肯定,用于進行技術研究工作或線上商業(yè)化項目,那在這里會給大家僅列舉F-Stack用戶實際現網業(yè)務的實踐案例。
(一)騰訊云HttpDNS
HttpDNS服務主要用于移動端APP,解決其默認DNS大量存在的解析失敗,解析結果跨網,解析劫持等問題,目前各大TOP APP大部分都有使用此類技術,而騰訊云DNSPod作為最早推出商用HttpDNS服務,目前服務大量用戶,日請求量萬億級,歷史版本介紹可參考公眾號“鵝廠網事”上的文章《千億級HttpDNS服務是怎樣煉成的》,當然目前最新的HttpDNS 也已經迭代更新了多個版本,新的專業(yè)版支持了更多的特性功能,如IPv6,DNSPod權威數據推送,用戶自定義域名解析,危險域名攔截(用戶自定義是否開啟及攔截哪些類別的危險域名),黑白名單,請求統(tǒng)計等一系列功能,也都構建在 F-Stack基礎架構之上。
(二)DNSPod權威DNS
作為F-Stack的父項目,DNSPod權威DNS為近千萬域名提供權威解析服務,受益于F-Stack的高性能網絡服務,最新版本的權威DNS已經在百G機型上達到了單機1億QPS的性能,具體見本人之前的一篇文章《基于F-Stack 的權威DNS單機1億QPS性能優(yōu)化實踐》,目前DNSPod總線上容量達到了數十億QPS,結合騰訊集團遍布全球的大帶寬節(jié)點部署和先進的防護設備及算法,DNSPod在客戶無感知情況下多次成功防護TB級以上的DDoS攻擊,最近一次發(fā)生在2021.8.27周五下午,多種攻擊方式混合攻擊,平臺受攻擊合計峰值超過5T。
四、其它用戶態(tài)協(xié)議棧介紹
VPP
VPP(https://fd.io/)由思科主導,多個大廠參與,其用戶態(tài)協(xié)議棧Host Stack由思科交換機協(xié)議棧發(fā)展而來,開源時間晚于F-Stack,但是是目前社區(qū)活躍度最高的用戶態(tài)協(xié)議棧。
MTCP
MTCP(http://shader.kaist.edu/mtcp/)Stack來自韓國KAIST,在業(yè)界也有廣泛的使用,主要問題是如其名字所示僅支持TCP。
Seastar
Seastar(https://github.com/scylladb/seastar)作為ScyllaDB的子項目,其Native stack在內網有較好的表現,內網場景使用較多。
LwIP
LwIP(http://savannah.nongnu.org/projects/lwip/)來自瑞典計算機科學院,輕量級協(xié)議棧,主要用于嵌入式系統(tǒng)等,但也有不少廠商基于LwIP進行修改移植支持自己的應用。
留言互動,好禮放送
在留言區(qū)寫下本文讀后感,點亮「點贊」和「在看」,截止到11月26日上午10點,留言區(qū)評論點贊數第一名可獲得視頻禮盒1個!↓↓

(視頻禮盒)
快來留言區(qū)寫下本文讀后感吧,分享你學習網絡架構F-Stack的收獲與感悟~
?推薦閱讀
超專業(yè)解析!10分鐘帶你搞懂Linux中直接I/O原理


??戳「閱讀原文」一鍵訂閱《云薦大咖》專欄,獲取騰訊云官方的行業(yè)技術解讀資訊~
