天天看點

Linux 網絡性能tuning向導

本文的目的不完全在于提供調優資訊,而是在于告訴讀者了解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 /隊列。 列将進入中斷的數量表示為計數器值:

Linux 網絡性能tuning向導

 SoftIRQs

也稱為“下半”中斷,軟體中斷請求(SoftIRQ)是核心線程,其被排程為在其他任務不會被中斷的時間運作。 SoftIRQ的目的是消費網絡擴充卡接收環緩沖區。 這些例程以ksoftirqd / cpu-number程序和調用驅動程式特定的代碼函數的形式運作。 它們可以在過程監控工具(如ps和top)中看到。 以下調用堆棧,從底部向上讀取,是一個SoftIRQ輪詢Mellanox卡的示例。 标記為[mlx4_en]的函數是mlx4_en.ko驅動程式核心子產品中的Mellanox輪詢例程,由核心的通用輪詢例程(如net_rx_action)調用。 從驅動程式移動到核心之後,接收到的流量将移動到套接字,準備應用程式使用:

Linux 網絡性能tuning向導

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

Linux 網絡性能tuning向導

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 kernel

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

Linux 網絡性能tuning向導

它使用此字段将skb路由到正确的裝置:

Linux 網絡性能tuning向導

基于此裝置,執行将切換到處理skb的驅動程式,并最終将資料複制到NIC上。 這裡主要需要調優的是TX隊列入隊規則(qdisc)稍後描述。 一些NIC可以有多個TX隊列。

以下是從測試系統擷取的示例堆棧跟蹤。 在這種情況下,流量是通過環回裝置,但這可以是任何NIC子產品:

Linux 網絡性能tuning向導

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

橋零複制發送

零拷貝發送模式減少了發送大資料包時的主機CPU開銷

之間的客戶網絡和外部網絡高達15%,而不影響

吞吐量。 紅帽企業版Linux 7完全支援橋接零拷貝傳輸

虛拟機,但預設情況下禁用。

零拷貝發送模式對大資料包大小有效。 它通常會減少主機CPU

當在客戶網絡和外部網絡之間傳輸大的資料包時,開銷将高達15%

網絡,而不影響吞吐量。

它不會影響客戶機到客戶機,客戶機到主機或小資料包工作負載的性能。

紅帽企業Linux 7虛拟機完全支援網橋零拷貝傳輸,但是

預設情況下禁用。 要啟用零拷貝傳輸模式,請設定experimental_zcopytx核心

vhost_net子產品的子產品參數設定為1。

Virtio 網卡 

這裡面還有一個細節非常影響性能,那就是virtio的feature裡面是否enable "rx mergeable",

disable這個feature的才能用到virtio pmd裡面最快的rx/tx函數(經過向量指令優化了的),

對應的兩個函數是virtio_xmit_pkts_simple()和virtio_recv_pkts_vec()。

SoftIRQ

如果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

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

使用如下腳本修改各個 CPU 調頻(實體機有 16 個實體 CPU)

#!/bin/bash

for

a in {

..

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導出子產品參數的目前設定例如,給出驅動程式參數:  

Linux 網絡性能tuning向導

 可以在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核心時的高速緩存未命中。

轉載于:https://www.cnblogs.com/scottieyuyang/p/6003873.html

繼續閱讀