Linux性能優化實戰學習筆記:第四十四講

1、上節回顧

上一節,咱們學了網絡性能優化的幾個思路,我先帶你簡單複習一下。算法

在優化網絡的性能時,你能夠結合 Linux 系統的網絡協議棧和網絡收發流程,而後從應用程序、套接字、傳輸層、網絡層再到鏈路層等每一個層次,進行逐層優化。上一期咱們主要
學習了應用程序和套接字的優化思路,好比:緩存

  • 在應用程序中,主要優化 I/O 模型、工做模型以及應用層的網絡協議;
  • 在套接字層中,主要優化套接字的緩衝區大小。

今天,咱們順着 TCP/IP 網絡模型,繼續向下,看看如何從傳輸層、網絡層以及鏈路層中,優化 Linux 網絡性能。性能優化

2、網絡性能優化-傳輸層

傳輸層最重要的是 TCP 和 UDP 協議,因此這兒的優化,其實主要就是對這兩種協議的優化。服務器

咱們首先來看 TCP 協議的優化。cookie

TCP 提供了面向鏈接的可靠傳輸服務。要優化 TCP,咱們首先要掌握 TCP 協議的基本原理,好比流量控制、慢啓動、擁塞避免、延遲確認以及狀態流圖(以下圖所示)等網絡

關於這些原理的細節,我就再也不展開講解了。若是你尚未徹底掌握,建議你先學完這些基本原理後再來優化,而不是囫圇吞棗地亂抄亂試。併發

掌握這些原理後,你就能夠在不破壞 TCP 正常工做的基礎上,對它進行優化。下面,我分幾類狀況詳細說明。tcp

第一類,在請求數比較大的場景下,你可能會看到大量處於 TIME_WAIT 狀態的鏈接,它們會佔用大量內存和端口資源。這時,咱們能夠優化與 TIME_WAIT 狀態相關的內核選
項,好比採起下面幾種措施。ide

  • 增大處於 TIME_WAIT 狀態的鏈接數量 net.ipv4.tcp_max_tw_buckets ,並增大鏈接跟蹤表的大小 net.netfilter.nf_conntrack_max。
  • 減少 net.ipv4.tcp_fin_timeout 和 net.netfilter.nf_conntrack_tcp_timeout_time_wait,讓系統儘快釋放它們所佔用的資源。
  • 開啓端口複用 net.ipv4.tcp_tw_reuse。這樣,被 TIME_WAIT 狀態佔用的端口,還能用到新建的鏈接中。
  • 增大本地端口的範圍 net.ipv4.ip_local_port_range 。這樣就能夠支持更多鏈接,提升總體的併發能力。
  • 增長最大文件描述符的數量。你可使用 fs.nr_open ,設置系統的最大文件描述符數;或在應用程序的 systemd 配置文件中,配置 LimitNOFILE ,設置應用程序的最大文件描述符數。

第二類,爲了緩解 SYN FLOOD 等,利用 TCP 協議特色進行攻擊而引起的性能問題,你能夠考慮優化與 SYN 狀態相關的內核選項,好比採起下面幾種措施。工具

  • 增大 TCP 半鏈接的最大數量 net.ipv4.tcp_max_syn_backlog ,或者開啓 TCP SYNCookies net.ipv4.tcp_syncookies ,來繞開半鏈接數量限制的問題(注意,這兩個選項不可同時使用)。
  • 減小 SYN_RECV 狀態的鏈接重傳 SYN+ACK 包的次數 net.ipv4.tcp_synack_retries。

第三類,在長鏈接的場景中,一般使用 Keepalive 來檢測 TCP 鏈接的狀態,以便對端鏈接斷開後,能夠自動回收。可是,系統默認的 Keepalive 探測間隔和重試次數,通常都無
法知足應用程序的性能要求。因此,這時候你須要優化與 Keepalive 相關的內核選項,比

  • 縮短最後一次數據包到 Keepalive 探測包的間隔時間 net.ipv4.tcp_keepalive_time;
  • 縮短髮送 Keepalive 探測包的間隔時間 net.ipv4.tcp_keepalive_intvl;
  • 減小 Keepalive 探測失敗後,一直到通知應用程序前的重試次數net.ipv4.tcp_keepalive_probes。

講了這麼多 TCP 優化方法,我也把它們整理成了一個表格,方便你在須要時參考(數值僅供參考,具體配置還要結合你的實際場景來調整):

優化 TCP 性能時,你還要注意,若是同時使用不一樣優化方法,可能會產生衝突。

好比,就像網絡請求延遲的案例中咱們曾經分析過的,服務器端開啓 Nagle 算法,而客戶端開啓延遲確認機制,就很容易致使網絡延遲增大。

另外,在使用 NAT 的服務器上,若是開啓 net.ipv4.tcp_tw_recycle ,就很容易致使各類鏈接失敗。實際上,因爲坑太多,這個選項在內核的 4.1 版本中已經刪除了。
說完 TCP,咱們再來看 UDP 的優化。

UDP 提供了面向數據報的網絡協議,它不須要網絡鏈接,也不提供可靠性保障。因此,UDP 優化,相對於 TCP 來講,要簡單得多。這裏我也總結了常見的幾種優化方案。

  • 跟上篇套接字部分提到的同樣,增大套接字緩衝區大小以及 UDP 緩衝區範圍。
  • 跟前面 TCP 部分提到的同樣,增大本地端口號的範圍;
  • 根據 MTU 大小,調整 UDP 數據包的大小,減小或者避免分片的發生。

3、網絡性能優化-網絡層

接下來,咱們再來看網絡層的優化。

網絡層,負責網絡包的封裝、尋址和路由,包括 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(Maximum Transmission Unit)的大小

一般,MTU 的大小應該根據以太網的標準來設置。以太網標準規定,一個網絡幀最大爲1518B,那麼去掉以太網頭部的 18B 後,剩餘的 1500 就是以太網 MTU 的大小。
在使用 VXLAN、GRE 等疊加網絡技術時,要注意,網絡疊加會使原來的網絡包變大,致使 MTU 也須要調整。

好比,就以 VXLAN 爲例,它在原來報文的基礎上,增長了 14B 的以太網頭部、 8B 的VXLAN 頭部、8B 的 UDP 頭部以及 20B 的 IP 頭部。換句話說,每一個包比原來增大了50B。
因此,咱們就須要把交換機、路由器等的 MTU,增大到 1550, 或者把 VXLAN 封包前(好比虛擬化環境中的虛擬網卡)的 MTU 減少爲 1450。

另外,如今不少網絡設備都支持巨幀,若是是這種環境,你還能夠把 MTU 調大爲 9000,以提升網絡吞吐量。

第三種,從 ICMP 的角度出發,爲了不 ICMP 主機探測、ICMP Flood 等各類網絡問題,你能夠經過內核選項,來限制 ICMP 的行爲。

  • 好比,你能夠禁止 ICMP 協議,即設置 net.ipv4.icmp_echo_ignore_all = 1。這樣,外部主機就沒法經過 ICMP 來探測主機。
  • 或者,你還能夠禁止廣播 ICMP,即設置 net.ipv4.icmp_echo_ignore_broadcasts =1。

4、網絡性能優化-鏈路層

網絡層的下面是鏈路層,因此最後,咱們再來看鏈路層的優化方法。

鏈路層負責網絡包在物理網絡中的傳輸,好比 MAC 尋址、錯誤偵測以及經過網卡傳輸網絡幀等。天然,鏈路層的優化,也是圍繞這些基本功能進行的。接下來,咱們從不一樣的幾
個方面分別來看。

將這些中斷處理程序調度到不一樣的 CPU 上執行

因爲網卡收包後調用的中斷處理程序(特別是軟中斷),須要消耗大量的 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 的組包功能。

最後,對於網絡接口自己,也有不少方法,能夠優化網絡的吞吐量。

  • 好比,你能夠開啓網絡接口的多隊列功能。這樣,每一個隊列就能夠用不一樣的中斷號,調度到不一樣 CPU 上執行,從而提高網絡的吞吐量。
  • 再如,你能夠增大網絡接口的緩衝區大小,以及隊列長度等,提高網絡傳輸的吞吐量(注意,這可能致使延遲增大)。
  • 你還可使用 Traffic Control 工具,爲不一樣網絡流量配置 QoS。

到這裏,我就從應用程序、套接字、傳輸層、網絡層,再到鏈路層,分別介紹了相應的網絡性能優化方法。經過這些方法的優化後,網絡性能就能夠知足絕大部分場景了。
最後,別忘了一種極限場景。還記得咱們學過的的 C10M 問題嗎?

在單機併發 1000 萬的場景中,對 Linux 網絡協議棧進行的各類優化策略,基本都沒有太大效果。由於這種狀況下,網絡協議棧的冗長流程,其實才是最主要的性能負擔。
這時,咱們能夠用兩種方式來優化。

第一種,使用 DPDK 技術,跳過內核協議棧,直接由用戶態進程用輪詢的方式,來處理網絡請求。同時,再結合大頁、CPU 綁定、內存對齊、流水線併發等多種機制,優化網絡包
的處理效率。

第二種,使用內核自帶的 XDP 技術,在網絡包進入內核協議棧前,就對其進行處理,這樣也能夠實現很好的性能。

5、小結

這兩節課,咱們一塊兒梳理了常見的 Linux 網絡性能優化方法。

在優化網絡的性能時,咱們能夠結合 Linux 系統的網絡協議棧和網絡收發流程,從應用程序、套接字、傳輸層、網絡層再到鏈路層等,對每一個層次進行逐層優化。

實際上,咱們分析和定位網絡瓶頸,也是基於這些網絡層進行的。而定位出網絡性能瓶頸後,咱們就能夠根據瓶頸所在的協議層,進行優化。具體而言:

  • 在應用程序中,主要是優化 I/O 模型、工做模型以及應用層的網絡協議;
  • 在套接字層中,主要是優化套接字的緩衝區大小;
  • 在傳輸層中,主要是優化 TCP 和 UDP 協議;
  • 在網絡層中,主要是優化路由、轉發、分片以及 ICMP 協議;
  • 最後,在鏈路層中,主要是優化網絡包的收發、網絡功能卸載以及網卡選項。

若是這些方法依然不能知足你的要求,那就能夠考慮,使用 DPDK 等用戶態方式,繞過內核協議棧;或者,使用 XDP,在網絡包進入內核協議棧前進行處理。

相關文章
相關標籤/搜索