上一節,咱們學了網絡性能優化的幾個思路,我先帶你簡單複習一下。算法
在優化網絡的性能時,你能夠結合 Linux 系統的網絡協議棧和網絡收發流程,而後從應用程序、套接字、傳輸層、網絡層再到鏈路層等每一個層次,進行逐層優化。上一期咱們主要
學習了應用程序和套接字的優化思路,好比:緩存
今天,咱們順着 TCP/IP 網絡模型,繼續向下,看看如何從傳輸層、網絡層以及鏈路層中,優化 Linux 網絡性能。性能優化
傳輸層最重要的是 TCP 和 UDP 協議,因此這兒的優化,其實主要就是對這兩種協議的優化。服務器
咱們首先來看 TCP 協議的優化。cookie
TCP 提供了面向鏈接的可靠傳輸服務。要優化 TCP,咱們首先要掌握 TCP 協議的基本原理,好比流量控制、慢啓動、擁塞避免、延遲確認以及狀態流圖(以下圖所示)等網絡
關於這些原理的細節,我就再也不展開講解了。若是你尚未徹底掌握,建議你先學完這些基本原理後再來優化,而不是囫圇吞棗地亂抄亂試。併發
掌握這些原理後,你就能夠在不破壞 TCP 正常工做的基礎上,對它進行優化。下面,我分幾類狀況詳細說明。tcp
第一類,在請求數比較大的場景下,你可能會看到大量處於 TIME_WAIT 狀態的鏈接,它們會佔用大量內存和端口資源。這時,咱們能夠優化與 TIME_WAIT 狀態相關的內核選
項,好比採起下面幾種措施。ide
第二類,爲了緩解 SYN FLOOD 等,利用 TCP 協議特色進行攻擊而引起的性能問題,你能夠考慮優化與 SYN 狀態相關的內核選項,好比採起下面幾種措施。工具
第三類,在長鏈接的場景中,一般使用 Keepalive 來檢測 TCP 鏈接的狀態,以便對端鏈接斷開後,能夠自動回收。可是,系統默認的 Keepalive 探測間隔和重試次數,通常都無
法知足應用程序的性能要求。因此,這時候你須要優化與 Keepalive 相關的內核選項,比
講了這麼多 TCP 優化方法,我也把它們整理成了一個表格,方便你在須要時參考(數值僅供參考,具體配置還要結合你的實際場景來調整):
優化 TCP 性能時,你還要注意,若是同時使用不一樣優化方法,可能會產生衝突。
好比,就像網絡請求延遲的案例中咱們曾經分析過的,服務器端開啓 Nagle 算法,而客戶端開啓延遲確認機制,就很容易致使網絡延遲增大。
另外,在使用 NAT 的服務器上,若是開啓 net.ipv4.tcp_tw_recycle ,就很容易致使各類鏈接失敗。實際上,因爲坑太多,這個選項在內核的 4.1 版本中已經刪除了。
說完 TCP,咱們再來看 UDP 的優化。
UDP 提供了面向數據報的網絡協議,它不須要網絡鏈接,也不提供可靠性保障。因此,UDP 優化,相對於 TCP 來講,要簡單得多。這裏我也總結了常見的幾種優化方案。
接下來,咱們再來看網絡層的優化。
網絡層,負責網絡包的封裝、尋址和路由,包括 IP、ICMP 等常見協議。在網絡層,最主要的優化,其實就是對路由、 IP 分片以及 ICMP 等進行調優。
在須要轉發的服務器中,好比用做 NAT 網關的服務器或者使用 Docker 容器時,開啓IP 轉發,即設置 net.ipv4.ip_forward = 1。
調整數據包的生存週期 TTL,好比設置 net.ipv4.ip_default_ttl = 64。注意,增大該值會下降系統性能。
開啓數據包的反向地址校驗,好比設置 net.ipv4.conf.eth0.rp_filter = 1。這樣能夠防止 IP 欺騙,並減小僞造 IP 帶來的 DDoS 問題。
一般,MTU 的大小應該根據以太網的標準來設置。以太網標準規定,一個網絡幀最大爲1518B,那麼去掉以太網頭部的 18B 後,剩餘的 1500 就是以太網 MTU 的大小。
在使用 VXLAN、GRE 等疊加網絡技術時,要注意,網絡疊加會使原來的網絡包變大,致使 MTU 也須要調整。
好比,就以 VXLAN 爲例,它在原來報文的基礎上,增長了 14B 的以太網頭部、 8B 的VXLAN 頭部、8B 的 UDP 頭部以及 20B 的 IP 頭部。換句話說,每一個包比原來增大了50B。
因此,咱們就須要把交換機、路由器等的 MTU,增大到 1550, 或者把 VXLAN 封包前(好比虛擬化環境中的虛擬網卡)的 MTU 減少爲 1450。
另外,如今不少網絡設備都支持巨幀,若是是這種環境,你還能夠把 MTU 調大爲 9000,以提升網絡吞吐量。
網絡層的下面是鏈路層,因此最後,咱們再來看鏈路層的優化方法。
鏈路層負責網絡包在物理網絡中的傳輸,好比 MAC 尋址、錯誤偵測以及經過網卡傳輸網絡幀等。天然,鏈路層的優化,也是圍繞這些基本功能進行的。接下來,咱們從不一樣的幾
個方面分別來看。
因爲網卡收包後調用的中斷處理程序(特別是軟中斷),須要消耗大量的 CPU。因此,將這些中斷處理程序調度到不一樣的 CPU 上執行,就能夠顯著提升網絡吞吐量。這一般能夠採
用下面兩種方法。
好比,你能夠爲網卡硬中斷配置 CPU 親和性(smp_affinity),或者開啓 irqbalance服務。
再如,你能夠開啓 RPS(Receive Packet Steering)和 RFS(Receive FlowSteering),將應用程序和軟中斷的處理,調度到相同 CPU 上,這樣就能夠增長 CPU
緩存命中率,減小網絡延遲。
TSO(TCP Segmentation Offload)和 UFO(UDP Fragmentation Offload):在TCP/UDP 協議中直接發送大包;而 TCP 包的分段(按照 MSS 分段)和 UDP 的分片(按照 MTU 分片)功能,由 網卡來完成 。
GSO(Generic Segmentation Offload):在網卡不支持 TSO/UFO 時,將 TCP/UDP包的分段,延遲到進入網卡前再執行。這樣,不只能夠減小 CPU 的消耗,還能夠在發生
丟包時只重傳分段後的包。
LRO(Large Receive Offload):在接收 TCP 分段包時,由網卡將其組裝合併後,再交給上層網絡處理。不過要注意,在須要 IP 轉發的狀況下,不能開啓 LRO,由於若是
多個包的頭部信息不一致,LRO 合併會致使網絡包的校驗錯誤。
GRO(Generic Receive Offload):GRO 修復了 LRO 的缺陷,而且更爲通用,同時支持 TCP 和 UDP。
RSS(Receive Side Scaling):也稱爲多隊列接收,它基於硬件的多個接收隊列,來分配網絡接收進程,這樣可讓多個 CPU 來處理接收到的網絡包。
VXLAN 卸載:也就是讓網卡來完成 VXLAN 的組包功能。
到這裏,我就從應用程序、套接字、傳輸層、網絡層,再到鏈路層,分別介紹了相應的網絡性能優化方法。經過這些方法的優化後,網絡性能就能夠知足絕大部分場景了。
最後,別忘了一種極限場景。還記得咱們學過的的 C10M 問題嗎?
在單機併發 1000 萬的場景中,對 Linux 網絡協議棧進行的各類優化策略,基本都沒有太大效果。由於這種狀況下,網絡協議棧的冗長流程,其實才是最主要的性能負擔。
這時,咱們能夠用兩種方式來優化。
第一種,使用 DPDK 技術,跳過內核協議棧,直接由用戶態進程用輪詢的方式,來處理網絡請求。同時,再結合大頁、CPU 綁定、內存對齊、流水線併發等多種機制,優化網絡包
的處理效率。
第二種,使用內核自帶的 XDP 技術,在網絡包進入內核協議棧前,就對其進行處理,這樣也能夠實現很好的性能。
這兩節課,咱們一塊兒梳理了常見的 Linux 網絡性能優化方法。
在優化網絡的性能時,咱們能夠結合 Linux 系統的網絡協議棧和網絡收發流程,從應用程序、套接字、傳輸層、網絡層再到鏈路層等,對每一個層次進行逐層優化。
實際上,咱們分析和定位網絡瓶頸,也是基於這些網絡層進行的。而定位出網絡性能瓶頸後,咱們就能夠根據瓶頸所在的協議層,進行優化。具體而言:
若是這些方法依然不能知足你的要求,那就能夠考慮,使用 DPDK 等用戶態方式,繞過內核協議棧;或者,使用 XDP,在網絡包進入內核協議棧前進行處理。