天天看點

44-套路篇:網絡性能優化的幾個思路(下)

網絡性能優化

傳輸層

傳輸層最重要的是TCP和UDP協定,是以這兒的優化,其實主要就是對這兩種協定的優化

TCP協定的優化

TCP提供了面向連接配接的可靠傳輸服務

要優化TCP首先要掌握TCP協定的基本原理

比如流量控制、慢啟動、擁塞避免、延遲确認以及狀态流圖(如下圖所示)等

44-套路篇:網絡性能優化的幾個思路(下)

分幾類情況詳細說明

  1. 第一類,在請求數比較大的場景下,可能會看到大量處于TIME_WAIT狀态的連接配接

    它們會占用大量記憶體和端口資源

    這時,可以優化與TIME_WAIT狀态相關的核心選項,比如采取下面幾種措施

    1. 增大處于TIME_WAIT狀态的連接配接數量net.ipv4.tcp_max_tw_buckets

      并增大連接配接跟蹤表的大小net.netfilter.nf_conntrack_max

    2. 減小net.ipv4.tcp_fin_timeout和net.netfilter.nf_conntrack_tcp_timeout_time_wait

      讓系統盡快釋放它們所占用的資源

    3. 開啟端口複用net.ipv4.tcp_tw_reuse

      這樣被TIME_WAIT狀态占用的端口,還能用到建立的連接配接中

    4. 增大學地端口的範圍net.ipv4.ip_local_port_range

      這樣就可以支援更多連接配接,提高整體的并發能力

    5. 增加最大檔案描述符的數量

      可以使用fs.nr_open ,設定系統的最大檔案描述符數

      或在應用程式的systemd配置檔案中,配置LimitNOFILE,設定應用程式的最大檔案描述符數

  2. 第二類,為了緩解SYN FLOOD等

    利用TCP協定特點進行攻擊而引發的性能問題,可以考慮優化與SYN狀态相關的核心選項

    比如采取下面幾種措施

    1. 增大TCP半連接配接的最大數量net.ipv4.tcp_max_syn_backlog

      或者開啟TCP SYN Cookies net.ipv4.tcp_syncookies

      來繞開半連接配接數量限制的問題(注意這兩個選項不可同時使用)

    2. 減少SYN_RECV狀态的連接配接重傳SYN+ACK包的次數net.ipv4.tcp_synack_retries
  3. 第三類,在長連接配接的場景中,通常使用Keepalive來檢測TCP連接配接的狀态

    以便對端連接配接斷開後,可以自動回收

    但是系統預設的Keepalive探測間隔和重試次數,一般都無法滿足應用程式的性能要求

    是以這時候需要優化與Keepalive相關的核心選項,比如

    1. 縮短最後一次資料包到Keepalive探測包的間隔時間net.ipv4.tcp_keepalive_time
    2. 縮短發送Keepalive探測包的間隔時間net.ipv4.tcp_keepalive_intvl
    3. 減少Keepalive探測失敗後,一直到通知應用程式前的重試次數net.ipv4.tcp_keepalive_probes
44-套路篇:網絡性能優化的幾個思路(下)

優化TCP性能時,還要注意,如果同時使用不同優化方法,可能會産生沖突

比如就像網絡請求延遲案例中,伺服器端開啟Nagle算法,用戶端開啟延遲确認機制,就很容易導緻網絡延遲增大

另外在使用NAT的伺服器上,如果開啟net.ipv4.tcp_tw_recycle ,就很容易導緻各種連接配接失敗

實際上,由于坑太多,這個選項在核心的4.1版本中已經删除了

UDP協定的優化

UDP提供了面向資料報的網絡協定,它不需要網絡連接配接,也不提供可靠性保障

是以UDP 優化,相對于 TCP 來說,要簡單得多

  1. 跟上篇套接字部分提到的一樣,增大套接字緩沖區大小以及UDP緩沖區範圍
  2. 跟前面TCP部分提到的一樣,增大學地端口号的範圍
  3. 根據MTU大小,調整UDP資料包的大小,減少或者避免分片的發生

網絡層

網絡層負責網絡包的封裝、尋址和路由,包括IP、ICMP等常見協定

在網絡層最主要的優化,其實就是對路由、 IP分片以及ICMP等進行調優

  1. 第一種從路由和轉發的角度出發,可以調整下面的核心選項
    1. 在需要轉發的伺服器中,比如用作NAT網關的伺服器或者使用Docker容器時

      開啟IP轉發,即設定net.ipv4.ip_forward = 1

    2. 調整資料包的生存周期TTL,比如設定net.ipv4.ip_default_ttl = 64

      注意增大該值會降低系統性能

    3. 開啟資料包的反向位址校驗,比如設定net.ipv4.conf.eth0.rp_filter = 1

      這樣可以防止IP欺騙,并減少僞造IP帶來的DDoS問題

  2. 第二種,從分片的角度出發,最主要的是調整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, 以提高網絡吞吐量

  3. 第三種,從ICMP的角度出發,為了避免ICMP主機探測、ICMP Flood等各種網絡問題

    可以通過核心選項,來限制ICMP的行為

    1. 禁止ICMP協定,即設定net.ipv4.icmp_echo_ignore_all = 1

      這樣,外部主機就無法通過ICMP來探測主機

    2. 禁止廣播ICMP,即設定net.ipv4.icmp_echo_ignore_broadcasts = 1

鍊路層

網絡層的下面是鍊路層,是以最後再來看鍊路層的優化方法

鍊路層負責網絡包在實體網絡中的傳輸,比如MAC尋址、錯誤偵測以及通過網卡傳輸網絡幀等

自然鍊路層的優化,也是圍繞這些基本功能進行的

由于網卡收包後調用的中斷處理程式(特别是軟中斷),需要消耗大量的CPU

是以将這些中斷處理程式排程到不同的CPU上執行,就可以顯著提高網絡吞吐量

這通常可以采 用下面兩種方法

  1. 可以為網卡硬中斷配置CPU親和性(smp_affinity),或者開啟irqbalance服務
  2. 可以開啟RPS(Receive Packet Steering)和RFS(Receive Flow Steering)

    将應用程式和軟中斷的處理排程到相同CPU上,這樣就可以增加CPU緩存命中率,減少網絡延遲

另外現在的網卡都有很豐富的功能,原來在核心中通過軟體處理的功能,可以解除安裝到網卡中,通過硬體來執行

  1. TSO(TCP Segmentation Offload)和UFO(UDP Fragmentation Offload)

    在TCP/UDP協定中直接發送大包

    而TCP包的分段(按照MSS分段)和UDP的分片 (按照MTU分片)功能,由網卡來完成

  2. GSO(Generic Segmentation Offload)

    在網卡不支援TSO/UFO時,将TCP/UDP包的分段,延遲到進入網卡前再執行

    這樣,不僅可以減少CPU的消耗,還可以在發生丢包時隻重傳分段後的包

  3. LRO(Large Receive Offload)

    在接收TCP分段包時,由網卡将其組裝合并後,再交給上層網絡處理

    不過要注意,在需要IP轉發的情況下,不能開啟LRO

    因為如果多個包的頭部資訊不一緻,LRO合并會導緻網絡包的校驗錯誤

  4. GRO(Generic Receive Offload)

    GRO修複了LRO的缺陷,并且更為通用,同時支援TCP和UDP

  5. RSS(Receive Side Scaling)

    也稱為多隊列接收,它基于硬體的多個接收隊列,來配置設定網絡接收程序,這樣可以讓多個 CPU 來處理接收到的網絡包

  6. VXLAN 解除安裝

    也就是讓網卡來完成VXLAN的組包功能

最後對于網絡接口本身,也有很多方法,可以優化網絡的吞吐量

  1. 可以開啟網絡接口的多隊列功能

    這樣每個隊列就可以用不同的中斷号,排程到不同CPU上執行,進而提升網絡的吞吐量

  2. 可以增大網絡接口的緩沖區大小,以及隊列長度等,提升網絡傳輸的吞吐量 (注意,這可能導緻延遲增大)
  3. 可以使用Traffic Control工具,為不同網絡流量配置QoS

到這裡就從應用程式、套接字、傳輸層、網絡層,再到鍊路層,分别介紹了相應的網絡性能優化方法

通過這些方法的優化後,網絡性能就可以滿足絕大部分場景了

最後别忘了一種極限場景,C10M問題嗎?

在單機并發1000萬的場景中,對Linux網絡協定棧進行的各種優化政策,基本都沒有太大效果

因為這種情況下,網絡協定棧的冗長流程,其實才是最主要的性能負擔

這時可以用兩種方式來優化

  1. 第一種,使用 DPDK 技術,跳過核心協定棧,直接由使用者态程序用輪詢的方式,來處理網絡請求

    同時,再結合大頁、CPU綁定、記憶體對齊、流水線并發等多種機制,優化網絡包的處理效率

  2. 第二種,使用核心自帶的XDP技術,在網絡包進入核心協定棧前,就對其進行處理

    這樣也可以實作很好的性能

小結

在優化網絡的性能時

可以結合Linux系統的網絡協定棧和網絡收發流程,從應用程 序、套接字、傳輸層、網絡層再到鍊路層等

對每個層次進行逐層優化

實際上分析和定位網絡瓶頸,也是基于這些網絡層進行的

而定位出網絡性能瓶頸後,就可以根據瓶頸所在的協定層,進行優化

  1. 在應用程式中,主要是優化I/O模型、工作模型以及應用層的網絡協定
  2. 在套接字層中,主要是優化套接字的緩沖區大小
  3. 在傳輸層中,主要是優化TCP和UDP協定
  4. 在網絡層中,主要是優化路由、轉發、分片以及ICMP協定
  5. 在鍊路層中,主要是優化網絡包的收發、網絡功能解除安裝以及網卡選項

如果這些方法依然不能滿足要求,那就可以考慮,使用DPDK等使用者态方式,繞過核心協定棧

或者,使用XDP,在網絡包進入核心協定棧前進行處理

轉載請注明出處喲~

https://www.cnblogs.com/lichengguo