首頁 > 軟體

Linux 網路效能tuning向導

2020-06-16 17:29:51

本文的目的不完全在於提供調優資訊,而是在於告訴讀者了解Linux kernel如何處理封包,從而能夠在自己的實踐中發揮Linux 核心協定棧最大的效能

The NIC ring buffer

接收環緩衝區在裝置驅動程式和NIC之間共用。 網絡卡分配傳送(TX)和接收(RX)環形緩衝區。 環形緩衝區是一個迴圈緩衝區,其中溢位只是覆蓋現有資料。 應該注意,有兩種方式將資料從NIC移動到核心,硬體中斷和軟體中斷(也稱為SoftIRQ)。 RX環形緩衝區用於儲存傳入的封包,直到它們被裝置驅動程式處理。 裝置驅動程式通常通過SoftIRQ消費RX環,這將進入的封包放入稱為sk_buff或“skb”的核心資料結構中,以開始其通過核心並到達擁有相關通訊端的應用程式。 TX環形緩衝區用於儲存發往該線路的輸出封包。 這些環形緩衝器位於堆疊的底部,並且是可能發生分組丟棄的關鍵點,這又會不利地影響網路效能。

Interrupts and Interrupt Handlers

來自硬體的中斷稱為“上半部分”中斷。 當NIC接收到傳入資料時,它使用DMA將資料複製到核心緩衝區中。 NIC通過喚醒硬中斷通知核心此資料。 這些中斷由中斷處理程式處理,這些中斷處理程式執行最少的工作,因為它們已經中斷了另一個任務,並且不能自行中斷。 硬中斷在CPU使用方面可能是昂貴的,特別是在持有核心鎖時。 硬中斷處理程式然後將大部分分組接收留給可以更公平地排程的軟體中斷或SoftIRQ處理。

硬中斷可以在/ proc / interrupts中看到,其中每個佇列在分配給它的第一列中有一個中斷向量。 當系統引導或載入NIC裝置驅動程式模組時,這些初始化。 每個RX和TX佇列被分配一個唯一的向量,它通知中斷處理程式該中斷來自哪個NIC /佇列。 列將進入中斷的數量表示為計數器值:

 SoftIRQs

也稱為“下半”中斷,軟體中斷請求(SoftIRQ)是核心執行緒,其被排程為在其他任務不會被中斷的時間執行。 SoftIRQ的目的是消費網路介面卡接收環緩衝區。 這些例程以ksoftirqd / cpu-number進程和呼叫驅動程式特定的程式碼函數的形式執行。 它們可以在過程監控工具(如ps和top)中看到。 以下呼叫堆疊,從底部向上讀取,是一個SoftIRQ輪詢Mellanox卡的範例。 標記為[mlx4_en]的函數是mlx4_en.ko驅動程式核心模組中的Mellanox輪詢例程,由核心的通用輪詢例程(如net_rx_action)呼叫。 從驅動程式移動到核心之後,接收到的流量將移動到通訊端,準備應用程式使用:

可以如下監視SoftIRQ。 每列代表一個CPU:

NAPI Polling

NAPI或新的API,以使處理傳入卡的封包更有效率。 硬中斷是昂貴的,因為它們不能被中斷。 即使中斷聚合(稍後更詳細地描述),中斷處理程式也將完全獨佔CPU核心。 NAPI的設計允許驅動程式進入輪詢模式,而不是每次需要的封包接收都被硬中斷。 在正常操作下,引發初始硬中斷或IRQ,隨後是使用NAPI例程輪詢卡的SoftIRQ處理器。 輪詢例程具有確定允許程式碼的CPU時間的預算。 這是防止SoftIRQ獨占CPU的必要條件。 完成後,核心將退出輪詢例程並重新建立,然後整個過程將重複自身。

Network Protocol Stacks

一旦已經從NIC接收到到核心的業務,則其然後由協定處理器(例如乙太網,ICMP,IPv4,IPv6,TCP,UDP和SCTP)處理。最後,資料被傳遞到通訊端緩衝器, 執行接收函數,將資料從核心空間移動到使用者空間,並結束核心在接收過程中的參與。

Packet egress in the Linux kerne

Linux核心的另一個重要方面是網路包出口。 雖然比入口邏輯簡單,但出口仍然值得確認。 當skbs從協定層傳遞到核心核心網路例程時,該過程工作。 每個skb包含一個dev欄位,其中包含將通過其傳輸的net_device的地址:

它使用此欄位將skb路由到正確的裝置:

基於此裝置,執行將切換到處理skb的驅動程式,並最終將資料複製到NIC上。 這裡主要需要調優的是TX佇列入隊規則(qdisc)稍後描述。 一些NIC可以有多個TX佇列。
以下是從測試系統獲取的範例堆疊跟蹤。 在這種情況下,流量是通過環迴裝置,但這可以是任何NIC模組:

 

Networking Tools 

要正確診斷網路效能問題,可以使用以下工具:

netstat 

一個命令列實用程式,可以列印有關開啟網路連線和協定棧統計資訊。 它從/ proc / net /檔案系統檢索有關網路子系統的資訊。 這些檔案包括:

•/ proc / net / dev(裝置資訊)

•/ proc / net / tcp(TCP通訊端資訊)

•/ proc / net / unix(Unix域通訊端資訊)

有關netstat及其參照檔案的更多資訊 / proc / net /,請參考netstat手冊頁:man netstat。

dropwatch 

監視實用程式,用於監視核心從記憶體釋放的封包。 有關更多資訊,請參閱dropwatch手冊頁:man dropwatch。

ip 

用於管理和監視路由,裝置,策略路由和隧道的實用程式。 有關更多資訊,請參閱ip手冊頁:man ip

ethtool 

用於顯示和更改NIC設定的實用程式。 有關更多資訊,請參閱ethtool手冊頁:man ethtool。

各種工具可用於隔離問題區域。

通過調查以下幾點來找到瓶頸:

•介面卡韌體級別 - 在ethtool -S ethX統計資訊中觀察丟棄

•介面卡驅動程式級別

•Linux核心,IRQ或SoftIRQs - 檢查/ proc /中斷和/ proc / net / softnet_stat

• 協定層IP,TCP或UDP - 使用netstat -s並查詢錯誤計數器

Performance Tuning

如果SoftIRQ沒有執行足夠長的時間,傳入資料的速率可能超過核心足夠快地耗盡緩衝區的能力。 因此,NIC緩衝區將溢位並且流量將丟失。 有時,有必要增加SoftIRQ允許在CPU上執行的時間。 這被稱為netdev_budget。 預算的預設值為300.

# sysctl net.core.netdev_budget

net.core.netdev_budget = 300 

Tuned 

Tuned是一個自適應系統調優守護程式。 它可以用於將收集在一起的各種系統設定應用到稱為組態檔的集合中。 調整後的組態檔可以包含諸如CPU排程器,IO排程程式和核心可調引數(如CPU排程或虛擬記憶體管理)的指令。 Tuned還整合了一個監視守護程式,可以控制或禁用CPU,磁碟和網路裝置的節能功能。 效能調整的目的是應用能夠實現最佳效能的設定。 Tuned可以自動化這項工作的很大一部分。 首先,安裝調優,啟動調整守護程式服務,並在啟動時啟用服務:

# yum -y install tuned

# service tuned start

# chkconfig tuned on

列出效能組態檔:

# tuned-adm list

Available profiles:

- throughput-performance

- default

- desktop-powersave

- enterprise-storage

...

可以在/ etc / tune-profiles /目錄中檢視每個組態檔的內容。 我們關心的是設定效能組態檔,如吞吐量效能,延遲效能或企業級儲存

設定組態檔:

# tuned-adm profile throughput-performance

Switching to profile 'throughput-performance'

所選組態檔將在每次調諧服務啟動時應用。 

The virtualization-related profiles provided as part of tuned-adm include:
virtual-guest
Based on the enterprise-storage profile, virtual-guest also decreases the swappiness of virtual memory. This profile is available in Red Hat Enterprise Linux 6.3 and later, and is the recommended profile for guest machines.
virtual-host
Based on the enterprise-storage profile, virtual-host also decreases the swappiness of virtual memory and enables more aggressive writeback of dirty pages. This profile is available in Red Hat Enterprise Linux 6.3 and later, and is the recommended profile for virtualization hosts, including both KVM and Red Hat Enterprise Virtualization hosts.

Numad

與tuned類似,numad是一個守護行程,可以幫助在具有非統一記憶體存取(NUMA)架構的系統上的進程和記憶體管理。 Numad通過監視系統拓撲和資源使用情況來實現這一點,然後嘗試定位進程以實現高效的NUMA區域性性和效率,其中進程具有足夠大的記憶體大小和CPU負載。 numad服務還需要啟用cgroups(Linux核心控制組)。

預設情況下,從Red Hat Enterprise Linux 6.5開始,numad將管理使用超過300Mb記憶體使用率和50%一個核心CPU使用率的任何進程,並嘗試使用任何給定的NUMA節點高達85%的容量。 Numad可以使用man numad中描述的指令進行更細緻的調整。

CPU Power States

ACPI規範定義了各種級別的處理器功率狀態或“C狀態”,其中C0是操作狀態,C1是停止狀態,加上實現各種附加狀態的處理器製造商以提供額外的功率節省和相關優點,例如較低的溫度。不幸的是,在功率狀態之間的轉換在延遲方面是昂貴的。由於我們關注使系統的響應性盡可能高,期望禁用所有處理器“深度睡眠”狀態,僅保留操作和停止。這必須首先在系統BIOS或EFI韌體中完成。應禁用任何狀態,如C6,C3,C1E或類似。我們可以通過在GRUB引導載入程式設定中的核心行中新增processor.max_cstate = 1來確保核心從不請求低於C1的C狀態。在某些情況下,核心能夠覆蓋硬體設定,並且必須向具有Intel處理器的系統新增附加引數intel_idle.max_cstate = 0。處理器的睡眠狀態可以通過以下方式確認:

cat /sys/module/intel_idle/parameters/max_cstate

0

較高的值表示可以輸入附加的睡眠狀態。 powertop實用程式的Idle Stats頁面可以顯示每個C狀態花費的時間

使用如下指令碼修改各個 CPU 調頻(物理機有 16 個物理 CPU)

#!/bin/bash
for a in {0..15};
do echo $a;
echo 'performance' > /sys/devices/system/cpu/cpu$a/cpufreq/scaling_governor
cat /sys/devices/system/cpu/cpu$a/cpufreq/scaling_governor
done

BIOS 中修改

禁用物理機超執行緒

TurboBoost Disabled

Power Technology: Performance

Manual balancing of interrupts

對於高效能來說要關閉irqbalance,同時將irq於cpu進行系結

Ethernet Flow Control (a.k.a. Pause Frames)

暫停幀是介面卡和交換機埠之間的乙太網級流量控制。當RX或TX緩衝器變滿時,介面卡將傳送“暫停幀”。開關將以毫秒級或更小的時間間隔停止資料流動。這通常足以允許核心排出介面緩衝區,從而防止緩衝區溢位和隨後的封包丟棄或超限。理想地,交換機將在暫停時間期間緩衝輸入資料。然而,重要的是認識到這種級別的流控制僅在開關和介面卡之間。如果丟棄分組,則較高層(例如TCP)或者在UDP和/或多播的情況下的應用應當啟動恢復。需要在NIC和交換機埠上啟用暫停幀和流控制,以使此功能生效。有關如何在埠上啟用流量控制的說明,請參閱您的網路裝置手冊或供應商。

在此範例中,禁用流量控制:

# ethtool -a eth3 Pause parameters for eth3: 

Autonegotiate:off

RX: off

TX: off

開啟流量控制:

# ethtool -A eth3 rx on

# ethtool -A eth3 tx on 

要確認流量控制已啟用:

# ethtool -a eth3 Pause parameters for eth3:

Autonegotiate:off

RX: on

TX: on

Interrupt Coalescence (IC)

中斷聚合是指在發出硬中斷之前,網路介面將接收的流量或接收流量後經過的時間。中斷太快或太頻繁會導致系統效能不佳,因為核心停止(或“中斷”)正在執行的任務以處理來自硬體的中斷請求。中斷太晚可能導致流量沒有足夠快地從NIC中取出。更多的流量可能到達,覆蓋以前的流量仍然等待被接收到核心中,導致流量丟失。大多數現代的NIC和驅動程式支援IC,許多驅動程式允許驅動程式自動調節硬體產生的中斷數。 IC設定通常包括2個主要元件,時間和封包數量。時間是在中斷核心之前NIC將等待的微秒數(u-sec),並且數位是在中斷核心之前允許在接收緩衝器中等待的最巨量資料包數。 NIC的中斷聚合可以使用ethtool -c ethX命令檢視,並使用ethtool -C ethX命令進行調整。自適應模式使卡能夠自動調節IC。在自適應模式下,驅動程式將檢查流量模式和核心接收模式,並在執行中估計合併設定,以防止封包丟失。當接收到許多小封包時,這是有用的。更高的中斷聚結有利於頻寬超過延遲。 VOIP應用(等待時間敏感)可能需要比檔案傳輸協定(吞吐量敏感)少的聚結。不同品牌和型號的網路介面卡具有不同的功能和預設設定,因此請參閱介面卡和驅動程式的製造商文件。

在此系統上,預設啟用自適應RX:

# ethtool -c eth3 Coalesce parameters for eth3:

Adaptive RX: on  TX: off

stats-block-usecs: 0

sample-interval: 0

pkt-rate-low: 400000

pkt-rate-high: 450000

rx-usecs: 16

rx-frames:44

rx-usecs-irq: 0

rx-frames-irq: 0

以下命令關閉自適應IC,並通知介面卡在接收到任何流量後立即中斷核心:

# ethtool -C eth3 adaptive-rx off rx-usecs 0 rx-frames 0

比較理想的設定是允許至少一些分組在NIC中緩衝,並且在中斷核心之前至少有一些時間通過。 有效範圍可以從1到數百,取決於系統能力和接收的流量

The Adapter Queue

netdev_max_backlog是Linux核心中的佇列,其中流量在從NIC接收之後但在由協定棧(IP,TCP等)處理之前儲存。 每個CPU核心有一個積壓佇列。 給定核心的佇列可以自動增長,包含的封包數量可達netdev_max_backlog設定指定的最大值。 netif_receive_skb()核心函數將為封包找到相應的CPU,並將封包排入該CPU的佇列。 如果該處理器的佇列已滿並且已達到最大大小,則將丟棄封包。 要調整此設定,首先確定積壓是否需要增加。 / proc / net / softnet_stat檔案在第2列中包含一個計數器,該值在netdev backlog佇列溢位時遞增。 如果此值隨時間增加,則需要增加netdev_max_backlog。

softnet_stat檔案的每一行代表一個從CPU0開始的CPU核心:

第一列是中斷處理程式接收的幀數。 第2列是由於超過netdev_max_backlog而丟棄的幀數。 第三列是ksoftirqd跑出netdev_budget或CPU時間的次數。

其他列可能會根據版本Red Hat Enterprise Linux而有所不同。 使用以下範例,CPU0和CPU1的以下計數器是前兩行:

# cat softnet_stat

0073d76b 00000000 000049ae 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000d2 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000015c 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000002a 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

對於上面的範例,netdev_max_backlog不需要更改,因為丟棄數量保持在0:
 

For CPU0

Total droppedno_budget lock_contention

0073d76b 00000000 000049ae 00000000
For CPU1

Total droppedno_budget lock_contention

000000d2 00000000 00000000 00000000

每列中的統計資訊以十六進位制提供。 預設的netdev_max_backlog值為1000.然而,這對於以1Gbps操作的多個介面,或甚至以10Gbps的單個介面來說可能是不夠的。 嘗試將此值加倍並觀察/ proc / net / softnet_stat檔案。 如果值加倍,則降低丟包增加的速率,再次加倍並再次測試。 重複此過程,直到建立最佳大小,並且丟包率不增加。 可以使用以下命令更改積壓,其中X是要設定的所需值:
# sysctl -w net.core.netdev_max_backlog=X
 
 
Adapter RX and TX Buffer Tuning
 
介面卡緩衝區預設值通常設定為小於最大值。 通常,增加接收緩衝區大小單獨足以防止封包丟棄,因為它可以允許核心略微更多的時間來排空緩衝區。 結果,這可以防止可能的分組丟失。 以下介面具有8 KB緩衝區的空間,但僅使用1 KB:
 
# ethtool -g eth3 Ring parameters for eth3:
Pre-set maximums:
RX: 8192
RX Mini: 0
RX Jumbo: 0
TX: 8192
Current hardware settings:
RX: 1024
RX Mini: 0
RX Jumbo: 0
TX: 512 
將RX和TX緩衝器增加到最大值:
 
# ethtool -G eth3 rx 8192 tx 8192
 
 
 
Adapter Transmit Queue Length 
 
傳輸佇列長度值確定在傳輸之前可以排隊的封包數。 預設值1000通常適用於當今的高速10Gbps或甚至40Gbps網路。 但是,如果介面卡上的數位傳輸錯誤正在增加(紅色部分統計),請考慮將其倍增。
 

vpp2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::14f7:b8ff:fe72:a52f prefixlen 64 scopeid 0x20<link>
ether 16:f7:b8:72:a5:2f txqueuelen 1000 (Ethernet)
RX packets 15905 bytes 1534810 (1.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 15905 bytes 1534810 (1.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

 
Module parameters
每個網路介面驅動程式通常作為可載入的核心模組。 可以使用modprobe命令載入和解除安裝模組。 這些模組通常包含可用於進一步調整裝置驅動程式和NIC的引數。 可以使用modinfo <drivername>命令檢視這些引數。 記錄特定驅動程式引數超出了本文件的範圍。 有關這些引數的說明,請參閱硬體手冊,驅動程式文件或硬體供應商。 Linux核心通過sysfs路徑/ sys / module / <drivername> / parameters匯出模組引數的當前設定例如,給出驅動程式引數:
 
 可以在sysfs中檢查每個驅動程式引數的當前值。 例如,要檢查udp_rss引數的當前設定:
 
# ls /sys/module/mlx4_en/parameters
inline_thold  num_lro  pfcrx  pfctx  rss_mask  rss_xor  tcp_rss  udp_rss
# cat /sys/module/mlx4_en/parameters/udp_rss
1
 
 
Adapter Offloading
 
為了減少系統的CPU負載,現代網路介面卡具有將一些網路處理負載移動到網路介面卡上的解除安裝功能。 例如,核心可以向NIC提交大(最多64k)個TCP段,然後NIC將拆分為MTU大小的段。 這個特殊功能稱為TCP分段解除安裝(TSO)。
 
 

解除安裝設定由ethtool -K ethX管理。

常用設定包括:
•GRO:通用接收解除安裝

•LRO:大型接收解除安裝

•TSO:TCP分段解除安裝

•RX校驗和=接收資料完整性處理

•TX校驗和=傳送資料完整性處理(TSO所需)

Jumbo Frames

預設802.3乙太網幀大小為1518位元組,或1522位元組帶有VLAN標記。 乙太網報頭使用此位元組的18個位元組(或22個帶VLAN標記的位元組),留下1500位元組的有效最大有效載荷。 巨型幀是對乙太網的非正式擴充套件,網路裝置供應商已經做出了事實上的標準,將有效載荷從1500增加到9000位元組。

對於常規的乙太網幀,每個放置線上路上的1500位元組資料有18位元組的開銷,或者1.2%的開銷。使用巨幀,每個9000位元組的資料放置線上上有18位元組的開銷,或0.2%的開銷。以上計算假設沒有VLAN標籤,然而這樣的標籤將向開銷增加4個位元組,使得效率增益更加理想。當傳輸大量連續資料時,例如在兩個系統之間傳送大檔案,可以通過使用巨幀獲得上述效率。當傳輸少量資料(例如通常低於1500位元組的web請求)時,可能沒有從使用較大幀大小看到的增益,因為通過網路的資料將被包含在小幀內。對於要設定的巨幀,網路段(即廣播域)中的所有介面和網路裝置必須支援巨幀並啟用增加的幀大小。

TCP Timestamps

TCP時間戳是TCP協定的擴充套件,定義在RFC 1323 - TCP Extensions for High Performance - http://tools.ietf.org/html/rfc1323

TCP時間戳提供單調遞增計數器(在Linux上,計數器是自系統引導以來的毫秒),其可以用於更好地估計TCP對話的往返時間,導致更準確的TCP視窗和緩衝器計算。最重要的是,TCP時間戳還提供防止包裝序列號,因為TCP報頭將序列號定義為32位元欄位。給定足夠快的鏈路,該TCP序列號可以包裝。這導致接收器相信具有包裝數的段實際上比其先前段更早到達,並且不正確地丟棄該段。在1吉位元每秒鏈路上,TCP序列號可以在17秒內換行。在10吉位元每秒的鏈路上,這被減少到少至1.7秒。在快速鏈路上,啟用TCP時間戳應視為強制。 TCP時間戳提供了一種替代的非迴圈方法來確定段的年齡和順序,防止包裝的TCP序列號成為問題。

Ensure TCP Timestamps are enabled:

# sysctl net.ipv4.tcp_timestamps net.ipv4.tcp_timestamps = 1
If the above command indicates that tcp_timestamps = 0, enable TCP Timestamps:
# sysctl -w net.ipv4.tcp_timestamps=1

TCP SACK

基本TCP確認(ACK)僅允許接收器通知傳送器已經接收到哪些位元組。 當丟包發生時,這要求傳送方從丟失點重傳所有位元組,這可能是低效的。 SACK允許傳送方指定哪些位元組已經丟失以及哪些位元組已經被接收,因此傳送方只能重傳丟失的位元組。 在網路社群有一些研究表明啟用高頻寬鏈路上的SACK可能導致不必要的CPU週期用於計算SACK值,降低TCP連線的整體效率。 這項研究意味著這些鏈路是如此之快,重傳少量資料的開銷小於作為選擇性確認的一部分計算提供的資料的開銷。 除非有高延遲或高封包丟失,最有可能更好地保持SACK關閉在高效能網路。 SACK可以使用核心可調引數關閉:

# sysctl -w net.ipv4.tcp_sack=0

TCP Window Scaling

在原始TCP定義中,TCP段報頭僅包含用於TCP視窗大小的8位元值,這對於現代計算的鏈路速度和記憶體能力是不足的。 引入了TCP Window Scaling擴充套件以允許更大的TCP接收視窗。 這是通過向在TCP報頭之後新增的TCP選項新增縮放值來實現的。 真實的TCP接收視窗向左移位縮放因子值的值,最大大小為1,073,725,440位元組,或接近1千兆位元組。 TCP視窗縮放是在開啟每個TCP對話的三次TCP握手(SYN,SYN + ACK,ACK)期間協商的。 傳送方和接收方都必須支援“視窗縮放”視窗縮放選項才能工作。 如果一個或兩個參與者在它們的握手中不公布視窗縮放能力,則對談回退到使用原始的8位元TCP視窗大小。

預設情況下,在Red Hat Enterprise Linux上啟用TCP視窗縮放。 視窗縮放的狀態可以使用命令確認:

# sysctl net.ipv4.tcp_window_scaling

net.ipv4.tcp_window_scaling = 1 

TCP視窗縮放協商可以通過捕獲開啟對話的TCP握手的封包來檢視。 在封包捕獲中,檢查三個握手封包的TCP選項欄位。 如果任一系統的握手封包不包含TCP視窗縮放選項,則可能需要在該系統上啟用TCP視窗縮放。

TCP Buffer Tuning

一旦從網路介面卡處理網路流量,就嘗試直接接收到應用中。 如果不可能,資料在應用程式??通訊端緩衝區上排隊。 通訊端中有3個佇列結構

sk_rmem_alloc = {          counter = 121948        },      

sk_wmem_alloc = {          counter = 553        },        

sk_omem_alloc = {          counter = 0

sk_rmem_alloc是接收佇列

sk_wmem_alloc是傳送佇列

sk_omem_alloc是無序佇列,不在當前TCP視窗內的skbs被放置在此佇列中

還有sk_rcvbuf變數,它代表scoket可以接受的位元組數。 

例如:

當sk_rcvbuf = 125336

從上面的輸出可以計算出接收佇列幾乎已滿。 當sk_rmem_alloc> sk_rcvbuf時,TCP棧將呼叫“收縮”接收佇列的例程。 這是一種管家,核心將通過減少開銷來嘗試釋放接收佇列中的可用空間。 然而,這種操作帶來了CPU成本。 如果崩潰無法釋放足夠的空間用於附加流量,則資料被“修剪”,意味著資料從記憶體丟棄,並且分組丟失。 因此,最好圍繞這個條件,避免緩衝區折疊和修剪。 第一步是識別緩衝區折疊和修剪是否正在發生。

# netstat -sn | egrep “prune|collap”; sleep 30; netstat -sn | egrep “prune|collap”    

17671 packets pruned from receive queue because of socket buffer overrun    

18671 packets pruned from receive queue because of socket buffer overrun

 如果在此間隔期間數位增加,則需要調整。 第一步是增加網路和TCP接收緩衝區設定。 這是檢查應用程式是否呼叫setsockopt(SO_RCVBUF)的好時機。 如果應用程式呼叫此函數,這將覆蓋預設設定,並關閉通訊端自動調整其大小的能力。 接收緩衝區的大小將是應用程式指定的大小。 考慮從應用程式中刪除setsockopt(SO_RCVBUF)函數呼叫,並允許緩衝區大小自動調整。

Tuning tcp_rmem 

通訊端記憶體可調引數有三個值,描述最小值,預設值和最大值(以位元組為單位)。 大多數Red Hat Enterprise Linux版本的預設最大值為4MiB。 要檢視這些設定,請將其增加4倍:

# sysctl net.ipv4.tcp_rmem 

4096 87380 4194304

# sysctl -w net.ipv4.tcp_rmem=“16384 349520 16777216”

# sysctl net.core.rmem_max 4194304

# sysctl -w net.core.rmem_max=16777216

如果應用程式無法更改為刪除setsockopt(SO_RCVBUF),則增加最大通訊端接收緩衝區大小,這可以使用SO_RCVBUF通訊端選項設定。 僅當更改tcp_rmem的中間值時,才需要重新啟動應用程式。 更改tcp_rmem的第3個和最大值不需要重新啟動應用程式,因為這些值是通過自動調整動態分配的。

TCP Listen Backlog

當TCP通訊端由處於LISTEN狀態的伺服器開啟時,該通訊端具有其可以處理的最大數量的未接受的用戶端連線。 如果應用程式在處理用戶端連線時速度很慢,或者伺服器快速獲得許多新連線(通常稱為SYN Flood),則新連線可能丟失,或者可能會傳送稱為“SYN cookie”的特製回復包。 如果系統的正常工作負載使得SYN cookie經常被輸入到系統紀錄檔中,則應調整系統和應用程式以避免它們。

應用程式可以請求的最大積壓由net.core.somaxconn核心可調引數決定。 應用程式可以總是請求更大的積壓,但它只會得到一個大到這個最大值的積壓。 可以如下檢查和更改此引數

# sysctl net.core.somaxconn net.core.somaxconn = 128

# sysctl -w net.core.somaxconn=2048 net.core.somaxconn = 2048

# sysctl net.core.somaxconn net.core.somaxconn = 2048

更改最大允許積壓量後,必須重新啟動應用程式才能使更改生效。 此外,在更改最大允許積壓之後,必須修改應用程式以在其偵聽通訊端上實際設定較大的積壓。 下面是一個在C語言中增加通訊端積壓所需的更改的範例:

-   rc = listen(sockfd, 128);

+   rc = listen(sockfd, 2048);    

if (rc < 0)     {        

perror("listen() failed");        

close(sockfd);        

exit(-1);    

}

上述更改將需要從原始碼重新編譯應用程式。 如果應用程式設計為積壓是一個可設定的引數,這可以在應用程式的設定中更改,並且不需要重新編譯。

Advanced Window Scaling

您可能會看到“修剪”錯誤繼續增加,無論上述設定如何。在Red Hat Enterprise Linux 6.3和6.4中,有一個提交被新增到收取skb共用結構到通訊端的成本,在核心更新紀錄檔中描述為[net]更準確的skb truesize。這種改變具有更快地填充TCP接收佇列的效果,因此更快地擊中修剪條件。此更改已在Red Hat Enterprise Linux 6.5中恢復。如果接收緩衝區增加並且修剪仍然發生,則引數net.ipv4.tcp_adv_win_scale決定分配給資料的接收緩衝區與被通告為可用TCP視窗的緩衝區的比率。 Red Hat Enterprise Linux 5和6上的預設值為2,等於分配給應用程式資料的緩衝區的四分之一。在RedHat Enterprise Linux 7版本上,此預設值為1,導致一半的空間被通告為TCP視窗。在Red Hat Enterprise Linux 5和6上將此值設定為1將會減少通告的TCP視窗的影響,可能會阻止接收緩衝區溢位,從而阻止緩衝區修剪。

# sysctl net.ipv4.tcp_adv_win_scale 2

# sysctl -w net.ipv4.tcp_adv_win_scale=1

UDP Buffer Tuning 

UDP是一個比TCP簡單得多的協定。 由於UDP不包含對談可靠性,因此應用程式有責任識別和重新傳輸丟棄的封包。 沒有視窗大小的概念,並且協定不恢復丟失的資料。 唯一可用的調諧包括增加接收緩衝區大小。 但是,如果netstat -us報告錯誤,另一個潛在的問題可能會阻止應用程式排空其接收佇列。 如果netstat -us顯示“封包接收錯誤”,請嘗試增加接收緩衝區並重新測試。 該統計量還可以由於其他原因而遞增,諸如有效載荷資料小於UDP報頭建議的短分組或者其校驗和計算失敗的損壞分組,因此如果緩衝區調諧不需要,則可能需要更深入的調查 解決UDP接收錯誤。 UDP緩衝區可以以類似於最大TCP緩衝區的方式調整:

# sysctl net.core.rmem_max

124928

# sysctl -w net.core.rmem_max=16777216

更改最大大小後,需要重新啟動應用程式以使新設定生效。

RSS: Receive Side Scaling

RSS由許多常見的網路介面卡支援。 在接收資料時,NIC可以將資料傳送到多個佇列。 每個佇列可以由不同的CPU服務,允許有效的資料檢索。 RSS充當驅動程式和卡韌體之間的API,以確定封包如何跨CPU核心分布,其想法是將流量引導到不同CPU的多個佇列允許更快的吞吐量和更低的延遲。 RSS控制哪些接收佇列獲得任何給定的分組,無論卡是否偵聽特定的單播乙太網地址,它偵聽的多播地址,哪個佇列對或乙太網佇列獲得多播分組的副本等。

RSS Considerations

驅動程式是否允許設定佇列數量

某些驅動程式將根據硬體資源自動生成引導期間的佇列數。 對於其他,它可以通過ethtool -L進行設定。

•系統有多少個核心應設定RSS,以便每個佇列轉到不同的CPU核心。

RPS: Receive Packet Steering

接收封包轉向是RSS的核心級軟體實現。 它駐留在驅動程式上方的網路堆疊的較高層。 RSS或RPS應該是互斥的。 預設情況下禁用RPS。 RPS使用儲存在封包定義的rxhash欄位中的2元組或4元組雜湊,用於確定應該處理給定封包的CPU佇列。

RFS: Receive Flow Steering

接收流轉向在引導分組時考慮應用區域性性。 這避免了當流量到達執行應用程式的不同CPU核心時的快取記憶體未命中。

本文永久更新連結地址http://www.linuxidc.com/Linux/2016-11/136642.htm


IT145.com E-mail:sddin#qq.com