查看和修改 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 | 當內核處理速度比網卡接收速度慢時,這部分多出來的包就會被保存在網卡的接收隊列上,而該參數說明了這個隊列的數量上限。 |