全用戶態網絡開發套件F-Stack架構分析

F-Stack是一個全用戶態(kernel bypass)的高性能的網絡接入開發包,基於DPDK、FreeBSD協議棧、微線程接口等,適用於各種需要網絡接入的業務,用戶只需要關注業務邏輯,簡單的接入F-Stack即可實現高性能的網絡服務器。 本文介紹F-Stack的詳細架構及如何解決內核協議棧面臨的問題。

傳統內核協議棧的性能瓶頸

在傳統的內核協議棧中,網絡包處理存在諸多瓶頸,嚴重影響網絡包的收發性能。性能瓶頸主要包括以下幾個方面

 

  1. 局部性失效 - 一個數據包的處理可能跨多個CPU核心、緩存失效、NUMA不友好 一個數據包可能中斷在cpu0,內核態處理在cpu1,用戶態處理在cpu2, 這樣跨越多個核心,造成局部性失效,CPU緩存失效, 同時可能存在跨NUMA訪問內存,性能受到很大影響。
  2. 中斷處理 - 硬件中斷、軟中斷、上下文切換 當網絡中數據量很大時,大量的數據包產生頻繁的硬件中斷請求, 這些硬件中斷可以打斷之前較低優先級的軟中斷或者系統調用的執行過程, 如果這種打斷頻繁進行的話,將產生較高的性能開銷。 用戶態內核態的上下文切換和軟中斷都增加了額外的開銷。
  3. 內存拷貝 - 內核態和用戶態之間的內存拷貝 網絡數據包從網卡到應用程序需要經過如下的過程: 數據從網卡通過DMA等方式傳到內核開闢的緩衝區; 數據從內核空間複製到用戶態空間。 在Linux內核協議棧中,這個耗時甚至佔到了數據包整個處理流程的一半。
  4. 系統調用 - 軟中斷、上下文切換、鎖競爭 頻繁到達的硬件中斷或者軟中斷都可能隨時搶佔系統調用的運行,這也將產生大量的上下文切換開銷。 內核中一些資源如PCB表等都需要加鎖處理,大量的併發操作造成很大的性能浪費,特別是大量短連接的創建。

F-Stack總體架構

無共享架構

 

F-Stack使用了多進程的無共享架構,每個進程CPU、網卡隊列綁定,具有無競爭、零拷貝、線性擴展、NUMA友好等特點。

  • 各進程綁定獨立的網卡隊列和CPU,每個NUMA節點使用獨立的內存池,請求通過設置網卡RSS散落到各進程進行處理,解決了局部性失效的問題。
  • 使用DPDK的輪詢模式,排除中斷處理造成的性能影響。
  • 使用DPDK作爲網絡I/O模塊,將數據包從網卡直接接收到用戶態,減少內核態到用戶態的內存拷貝。
  • 請求平均分配到每個核上,通過設置DPDK的rss hash函數保證相同ip、port的請求落到同一個核上。
  • 各進程擁有獨立的協議棧、PCB表等資源,消除了協議處理過程中的各種資源競爭。
  • 進程之間不共享內存,通過無鎖環形隊列(rte_ring)傳遞通信,如ARP包等。

 

用戶態協議棧

移植FreeBSD協議棧至用戶態。 通過外加頭文件、宏控制、以及hook相關實現進行的移植,對FreeBSD源代碼的修改不到100行, 對後續的跟進社區,升級版本非常友好。

 

  • 內存分配相關函數重新hook實現。(當前使用mmap和malloc,後續會替換成rte_mempool和rte_malloc)
  • 定時器使用rte_timer驅動,ticks定時更新,timecounter定時執行。
  • 移除內核線程、中斷線程等,統一進行輪詢處理。
  • 移除文件系統相關的綁定。
  • 移除FreeBSD內核中的所有鎖,用空的宏替換掉。
  • 其他glue code。

類posix接口和微線程框架

提供了類posix接口和微線程框架,方便現有應用接入,替換接口。 後續我們會提供類似LD_PRELOAD的方式,使得現有程序儘量無改動遷移到F-Stack。 微線程框架,移植自騰訊開源的毫秒服務MSEC裏使用的spp_rpc。 具有同步編程、異步執行的特點,無需處理複雜的異步邏輯。

 

問題及優化

  • CPU 100% 由於使用的DPDK輪詢模式,cpu使用率會一直是100%, 後續會引入DPDK的輪詢+中斷模式,當連續幾次輪詢沒有收到包後, 轉爲中斷模式,有包後持續輪詢,直到又沒包進來。
  • 常規網絡工具(如tcpdump、ifconfig、netstat等)無法使用 由於DPDK接管了網卡,所有的數據包都運行在用戶態,常規的網絡工具都無法使用, 爲此我們對一些工具進行了移植,目前已經完成了sysctl、ifconfig。 抓包可以在config.ini裏配置開啓,抓包文件也可以在wireshark裏直接分析。
  • Nginx reload 當前F-Stack的Nginx是運行在NGX_PROCESS_SINGLE模式下的, 各個進程互不關聯,無法使用原有的reload命令。後續會進行修復。

最佳實踐

  • 使用性能高的多核CPU,配置config.ini裏的lcore_mask(進程運行在哪些cpu上)運行多個進程。
  • 使用10G、25G、40G的多隊列網卡,支持硬件卸載功能,支持的RSS隊列數越多越好。
  • 配置儘可能多的Hugepage。
  • 配置config.ini關閉抓包。

Roadmap:

 

  • 繼續移植各種網絡配置工具,方便F-Stack在各種網絡環境(如GIF/GRE/VxLAN等隧道)下的部署使用。
  • 移植SPDK的用戶態驅動至F-Stack,提升磁盤I/O性能。
  • 增加對數據流的HOOK點/鏡像等,方便對數據包進行自定義處理。
  • 提供協議棧的相關優化模塊,如TCP加速、防護等。
  • 類posix接口提供LD_RRELOAD方式,簡化已有應用的接入方式。
  • 提供PHP/Python等語言的接口封裝,方便相關WEB服務的快速接入。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章