Linux 例項常用核心網路引數介紹與常見問題處理
本文總結了常見的 Linux 核心引數及相關問題。修改核心引數前,您需要:
- 從實際需要出發,最好有相關資料的支撐,不建議隨意調整核心引數。
- 瞭解引數的具體作用,且注意同類型或版本環境的核心引數可能有所不同。
- 備份 ECS 例項中的重要資料。參閱文件建立快照 。
檢視和修改 Linux 例項核心引數
方法一、通過/proc/sys/
目錄
檢視核心引數:使用 cat
檢視對應檔案的內容,例如執行命令 cat /proc/sys/net/ipv4/tcp_tw_recycle
檢視 net.ipv4.tcp_tw_recycle
的值。
修改核心引數:使用 echo
修改核心引數對應的檔案,例如執行命令 echo "0" > /proc/sys/net/ipv4/tcp_tw_recycle
將 net.ipv4.tcp_tw_recycle
的值修改為 0。
注意:
方法二、通過sysctl.conf
檔案
檢視核心引數:執行命令 sysctl -a
檢視當前系統中生效的所有引數,如下所示:
net.ipv4.tcp_app_win = 31 net.ipv4.tcp_adv_win_scale = 2 net.ipv4.tcp_tw_reuse = 0 net.ipv4.tcp_frto = 2 net.ipv4.tcp_frto_response = 0 net.ipv4.tcp_low_latency = 0 net.ipv4.tcp_no_metrics_save = 0 net.ipv4.tcp_moderate_rcvbuf = 1 net.ipv4.tcp_tso_win_divisor = 3 net.ipv4.tcp_congestion_control = cubic net.ipv4.tcp_abc = 0 net.ipv4.tcp_mtu_probing = 0 net.ipv4.tcp_base_mss = 512 net.ipv4.tcp_workaround_signed_windows = 0 net.ipv4.tcp_challenge_ack_limit = 1000 net.ipv4.tcp_limit_output_bytes = 262144 net.ipv4.tcp_dma_copybreak = 4096 net.ipv4.tcp_slow_start_after_idle = 1 net.ipv4.cipso_cache_enable = 1 net.ipv4.cipso_cache_bucket_size = 10 net.ipv4.cipso_rbm_optfmt = 0 net.ipv4.cipso_rbm_strictvalid = 1
修改核心引數:
-
執行命令
/sbin/sysctl -w kernel.parameter="example"
修改引數,如sysctl -w net.ipv4.tcp_tw_recycle="0"
。 -
執行命令
vi /etc/sysctl.conf
修改/etc/sysctl.conf
檔案中的引數。 -
執行命令
/sbin/sysctl -p
使配置生效。
注意:調整核心引數後核心處於不穩定狀態,請務必重啟例項。
Linux 網路相關核心引數引發的常見問題及處理
Linux 例項 NAT 雜湊表滿導致 ECS 例項丟包
此處涉及的核心引數:
net.netfilter.nf_conntrack_buckets net.nf_conntrack_max
問題現象
ECS Linux 例項出現間歇性丟包,無法連線例項,通過tracert、mtr
等工具排查,外部網路未見異常。同時,如下圖所示,在系統日誌中重複出現大量(table full, dropping packet.
)錯誤資訊。
Feb 6 16:05:07 i-*** kernel: nf_conntrack: table full, dropping packet. Feb 6 16:05:07 i-*** kernel: nf_conntrack: table full, dropping packet. Feb 6 16:05:07 i-*** kernel: nf_conntrack: table full, dropping packet. Feb 6 16:05:07 i-*** kernel: nf_conntrack: table full, dropping packet.
原因分析
ip_conntrack 是 Linux 系統內 NAT 的一個跟蹤連線條目的模組。ip_conntrack 模組會使用一個雜湊表記錄 TCP 協議 established connection 記錄,當這個雜湊表滿了的時候,便會導致nf_conntrack: table full, dropping packet
錯誤。Linux 系統會開闢一個空間用來維護每一個 TCP 連結,這個空間的大小與 nf_conntrack_buckets
、nf_conntrack_max
相關,後者的預設值是前者的 4 倍,而前者在系統啟動後無法修改,所以一般都是建議調大 nf_conntrack_max
。
注意:系統維護連線比較消耗記憶體,請在系統空閒和記憶體充足的情況下調大 nf_conntrack_max
,且根據系統的情況而定。
解決思路
- 使用管理終端 登入例項。
-
執行命令
# vi /etc/sysctl.conf
編輯系統核心配置。 -
修改雜湊表項最大值引數:
net.netfilter.nf_conntrack_max = 655350
。 -
修改超時引數:
net.netfilter.nf_conntrack_tcp_timeout_established = 1200
,預設情況下 timeout 是 432000(秒)。 -
執行命令
# sysctl -p
使配置生效。
Time wait bucket table overflow 報錯
此處涉及的核心引數:
-
net.ipv4.tcp_max_tw_buckets
問題現象
Linux 例項/var/log/message
日誌全是類似 kernel: TCP: time wait bucket table overflow
的報錯資訊,提示 time wait bucket table
溢位,如下:
Feb 18 12:28:38 i-*** kernel: TCP: time wait bucket table overflow Feb 18 12:28:44 i-*** kernel: printk: 227 messages suppressed. Feb 18 12:28:44 i-*** kernel: TCP: time wait bucket table overflow Feb 18 12:28:52 i-*** kernel: printk: 121 messages suppressed. Feb 18 12:28:52 i-*** kernel: TCP: time wait bucket table overflow Feb 18 12:28:53 i-*** kernel: printk: 351 messages suppressed. Feb 18 12:28:53 i-*** kernel: TCP: time wait bucket table overflow Feb 18 12:28:59 i-*** kernel: printk: 319 messages suppressed.
執行命令netstat -ant|grep TIME_WAIT|wc -l
統計處於 TIME_WAIT 狀態的 TCP 連線數,發現處於 TIME_WAIT 狀態的 TCP 連線非常多。
原因分析
引數net.ipv4.tcp_max_tw_buckets
可以調整核心中管理 TIME_WAIT 狀態的數量,當例項中處於 TIME_WAIT 及需要轉換為 TIME_WAIT 狀態連線數之和超過了 net.ipv4.tcp_max_tw_buckets
引數值時,message 日誌中將報錯 time wait bucket table
,同時核心關閉超出引數值的部分 TCP 連線。您需要根據實際情況適當調高 net.ipv4.tcp_max_tw_buckets
,同時從業務層面去改進 TCP 連線。
解決思路
-
執行命令
netstat -anp |grep tcp |wc -l
統計 TCP 連線數。 -
執行命令
vi /etc/sysctl.conf
,查詢net.ipv4.tcp_max_tw_buckets
引數。如果確認連線使用很高,容易超出限制。 -
調高參數
net.ipv4.tcp_max_tw_buckets
,擴大限制。 -
執行命令
# sysctl -p
使配置生效。
Linux 例項中 FIN_WAIT2 狀態的 TCP 連結過多
此處涉及的核心引數:
-
net.ipv4.tcp_fin_timeout
問題現象
FIN_WAIT2 狀態的 TCP 連結過多。
原因分析
- HTTP 服務中,Server 由於某種原因會主動關閉連線,例如 KEEPALIVE 超時的情況下。作為主動關閉連線的 Server 就會進入 FIN_WAIT2 狀態。
- TCP/IP 協議棧中,存在半連線 的概念,FIN_WAIT2 狀態不算做超時,如果 Client 不關閉,FIN_WAIT_2 狀態將保持到系統重啟,越來越多的 FIN_WAIT_2 狀態會致使核心 Crash。
-
建議調小
net.ipv4.tcp_fin_timeout
引數,減少這個數值以便加快系統關閉處於FIN_WAIT2
狀態的 TCP 連線。
解決思路
-
執行命令
vi /etc/sysctl.conf
,修改或加入以下內容:net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_max_syn_backlog = 8192 net.ipv4.tcp_max_tw_buckets = 5000
-
執行命令
# sysctl -p
使配置生效。
注意:由於
FIN_WAIT2
狀態的 TCP 連線會進入TIME_WAIT
狀態,請同時參閱 time wait bucket table overflow 報錯 。
Linux 例項中出現大量 CLOSE_WAIT 狀態的 TCP 連線
問題現象
執行命令netstat -atn|grep CLOSE_WAIT|wc -l
發現當前系統中處於 CLOSE_WAIT
狀態的 TCP 連線非常多。
原因分析
關閉 TCP 連線時,TCP 連線的兩端都可以發起關閉連線的請求,若對端發起了關閉連線,但本地沒有關閉連線,那麼該連線就會處於 CLOSE_WAIT 狀態。雖然該連線已經處於半開狀態,但是已經無法和對端通訊,需要及時的釋放掉該連結。建議從業務層面及時判斷某個連線是否已經被對端關閉,即在程式邏輯中對連線及時關閉檢查。
解決思路
程式語言中對應的讀、寫函式一般包含了檢測 CLOSE_WAIT TCP 連線功能,例如:
Java 語言:
-
通過
read
方法來判斷 I/O 。當 read 方法返回-1
時則表示已經到達末尾。 -
通過
close
方法關閉該連結。
C 語言:
-
檢查
read
的返回值。- 若等於 0 則可以關閉該連線。
- 若小於 0 則檢視 errno,若不是 AGAIN 則同樣可以關閉連線。
客戶端配置 NAT 後仍無法訪問 ECS 或 RDS 遠端伺服器
此處涉及的核心引數:
net.ipv4.tcp_tw_recycle net.ipv4.tcp_timestamps
問題現象
客戶端配置 NAT 後無法訪問遠端 ECS、RDS,包括配置了 SNAT 的 VPC ECS 。同時無法訪問連線其他 ECS 或 RDS 等雲產品,抓包檢測發現遠端對客戶端傳送的 SYN 包沒有響應。
原因分析
若遠端伺服器的核心引數net.ipv4.tcp_tw_recycle
和 net.ipv4.tcp_timestamps
的值都為 1,則遠端伺服器會檢查每一個報文中的時間戳(Timestamp),若 Timestamp 不是遞增的關係,不會響應這個報文。配置 NAT 後,遠端伺服器看到來自不同的客戶端的源 IP 相同,但 NAT 前每一臺客戶端的時間可能會有偏差,報文中的 Timestamp 就不是遞增的情況。
解決思路
-
遠端伺服器為 ECS 時,修改引數
net.ipv4.tcp_tw_recycle
為 0。 -
遠端伺服器為 RDS 等 PaaS 服務時。RDS 無法直接修改核心引數,需要在客戶端上修改引數
net.ipv4.tcp_tw_recycle
和net.ipv4.tcp_timestamps
為 0。
文件涉及的 Linux 核心引數說明
引數 | 說明 |
---|---|
net.ipv4.tcp_max_syn_backlog |
該引數決定了系統中處於SYN_RECV
狀態的 TCP 連線數量。SYN_RECV
狀態指的是當系統收到 SYN 後,作了 SYN+ACK 響應後等待對方回覆三次握手階段中的最後一個 ACK 的階段。 |
net.ipv4.tcp_syncookies |
該引數表示是否開啟 TCP 同步標籤(SYN_COOKIES
),核心必須開啟並編譯 CONFIG_SYN_COOKIES,SYN_COOKIES
可以防止一個套接字在有過多試圖連線到達時引起過載。預設值 0 表示關閉。當該引數被設定為 1 且 SYN_RECV
佇列滿了之後,核心會對 SYN 包的回覆做一定的修改,即,在響應的 SYN+ACK 包中,初始的序列號是由源 IP + Port、目的 IP + Port 及時間這五個引數共同計算出一個值組成精心組裝的 TCP 包。由於 ACK 包中確認的序列號並不是之前計算出的值,惡意攻擊者無法響應或誤判,而請求者會根據收到的 SYN+ACK 包做正確的響應。啟用 net.ipv4.tcp_syncookies
後,會忽略 net.ipv4.tcp_max_syn_backlog
。 |
net.ipv4.tcp_synack_retries |
該引數指明瞭處於SYN_RECV
狀態時重傳 SYN+ACK 包的次數。 |
net.ipv4.tcp_abort_on_overflow |
設定該引數為 1 時,當系統在短時間內收到了大量的請求,而相關的應用程式未能處理時,就會發送 Reset 包直接終止這些連結。建議通過優化應用程式的效率來提高處理能力,而不是簡單地 Reset。 預設值: 0。 |
net.core.somaxconn |
該引數定義了系統中每一個埠最大的監聽佇列的長度,是個全域性引數。該引數和net.ipv4.tcp_max_syn_backlog
有關聯,後者指的是還在三次握手的半連線的上限,該引數指的是處於 ESTABLISHED 的數量上限。若您的 ECS 例項業務負載很高,則有必要調高該引數。listen(2)
函式中的引數 backlog
同樣是指明監聽的埠處於 ESTABLISHED 的數量上限,當 backlog
大於 net.core.somaxconn
時,以 net.core.somaxconn
引數為準。 |
net.core.netdev_max_backlog | 當核心處理速度比網絡卡接收速度慢時,這部分多出來的包就會被儲存在網絡卡的接收佇列上,而該引數說明了這個佇列的數量上限。 |
參考連結
- Linux man-pages
- kernel/git/torvalds/linux.git_proc
- kernel/git/torvalds/linux.git_proc_net_tcp
- kernel/git/torvalds/linux.git_ip-sysctl
- kernel/git/torvalds/linux.git_netfilter-sysctl
- kernel/git/torvalds/linux.git_nf_conntrack-sysctl
來自 https://help.aliyun.com/knowledge_detail/41334.html