TCP內核參數的簡單驗證

前言

春節假期時學習了下內核參數與nginx的調優
最近因爲同事遇到問題一直沒有解,自己利用晚上時間再次進行驗證.
這裏將幾個參數的理解和驗證結果簡單總結一下.
希望能夠在學習的過程中將問題解決掉. 

其實很後悔沒有好好學習代碼.現在很多問題都已經到了瓶頸期
無法深入的研究下去. 

參數一

  • net.ipv4.tcp_max_tw_buckets
先說一下基本的結論:
CentOS默認的值: 262144
阿里雲虛擬機的默認值: 5000
華爲雲虛擬機的默認值: 5000
騰訊雲虛擬機的默認值: 131072

在簡單描述一下這個參數的作用: 
在 TIME_WAIT 數量等於 tcp_max_tw_buckets 時,
不會有新的 TIME_WAIT 產生。

類似 Nginx 之類的中間代理一定要關注這個值,因爲它對你的系統起到一個保護的作用,
一旦端口全部被佔用,服務就異常了。 
tcp_max_tw_buckets 能幫你降低這種情況的發生概率,爭取補救時間。
學習來源: https://www.jianshu.com/p/b7e991be0909

我這邊理解就類似於 JVM裏面GC over limited的處理機制相仿. 
能夠快速重用部分端口, 避免無端口可用無法建立新連接. 

參數二

  • net.ipv4.ip_local_port_range
這個參數 雲計算和CentOS的默認值出奇的一致: 
32768    60999
第一個參數代表隨機端口的下限
第二個參數代表建立TCP連接時端口的上限
C10K甚至是C100K的很多優化裏面都是需要改這個參數的

TCP是有四元素 local_ip local_port remote_ip remote_port 
來唯一確認一個TCP連接的.
理論上一個TCP的LISTEN的監聽端口可以建立很多個TCP連接的. 

參數三

  • net.ipv4.tcp_tw_reuse
個人感覺這個參數其實是存在一定風險的
可能會導致錯誤的TCP連接.
但是理論上 linux內核有TCP狀態的檢驗還有TCP的序列號進行串行化處理
幾乎零可能性的出現嚴重的數據問題. 

一個簡單的進行驗證的腳本

echo "443:" `netstat -anop |grep tcp |grep -v LISTEN |grep -v 637 |grep -v 884 |grep -v 1521 |grep -v tcp6 |grep -v :22 |grep :443 |awk '{++state[$6]} END {for(key in state) print key,state[key]}'`
echo "5000:" `netstat -anop |grep tcp |grep -v LISTEN |grep -v 637 |grep -v 884 |grep -v 1521 |grep -v tcp6 |grep -v :22 |grep :5000 |awk '{++state[$6]} END {for(key in state) print key,state[key]}'`
echo "5200:" `netstat -anop |grep tcp |grep -v LISTEN |grep -v 637 |grep -v 884 |grep -v 1521 |grep -v tcp6 |grep -v :22 |grep :520 |awk '{++state[$6]} END {for(key in state) print key,state[key]}'`

可以定量分析不同端口的連接信息. 

內核參數的驗證-1

修改內核參數
sysctl -w "net.ipv4.tcp_max_tw_buckets=50000"
登錄系統進行分析查看time wait的TCP數量. 
[root@openeuler2203 ~]#  netstat -anop |grep tcp |grep -v LISTEN |grep -v :637 |grep -v :884 |grep -v :1521 |grep -v tcp6 |grep -v :22 |grep :5200
tcp        0      0 10.110.139.230:5200     10.110.136.50:57506     TIME_WAIT   -                    timewait (0.71/0/0)
tcp        0      0 10.110.139.230:5200     10.110.136.50:37506     TIME_WAIT   -                    timewait (57.65/0/0)
tcp        0      0 10.110.139.230:5200     10.110.136.50:37604     TIME_WAIT   -                    timewait (57.94/0/0)
tcp        0      0 10.110.139.230:5200     10.110.136.50:57490     TIME_WAIT   -                    timewait (0.70/0/0)
tcp        0      0 10.110.139.230:5200     10.110.136.50:37708     TIME_WAIT   -                    timewait (58.02/0/0)
tcp        0      0 10.110.139.230:5200     10.110.136.50:37696     TIME_WAIT   -                    timewait (58.02/0/0)
tcp        0      0 10.110.139.230:5200     10.110.136.50:37630     TIME_WAIT   -                    timewait (57.96/0/0)
tcp        0      0 10.110.139.230:5200     10.110.136.50:57538     TIME_WAIT   -                    timewait (0.75/0/0)

發現會有40條 time wait的 tcp連接. 
最後一列是等待終結的time wait的tcp連接 等到所有的連接都停止後再次修改內核參數
sysctl -w "net.ipv4.tcp_max_tw_buckets=10"
# 注意我這種修改僅是驗證問題, 沒有生產適用性. 
# 注意每次測試至少要等待60秒等待之前的tcp連接終結. 

再次執行登錄簡單測試,效果爲:
[root@openeuler2203 ~]#  netstat -anop |grep tcp |grep -v LISTEN |grep -v :637 |grep -v :884 |grep -v :1521 |grep -v tcp6 |grep -v :22 |grep :5200
tcp        0      0 10.110.139.230:5200     10.110.136.50:59150     ESTABLISHED 716321/nginx: worke  off (0.00/0/0)

發現沒有再次生成 time wait的連接
# 注意這個參數是整個操作系統所有的time_wait的連接數 不單純是一個端口的. 所以10個肯定是不夠用的. 

內核參數驗證-2

直接修改參數: 
sysctl -w "net.ipv4.ip_local_port_range=3000 4000"
# 注意結果可以與內核參數驗證-1 裏面的結果進行對照. 
# 注意需要修改回 bucket的數據避免測試失效. 
[root@KylinV10SP3ARM64 nginx]# netstat -anop |grep tcp |grep -v LISTEN |grep -v 637 |grep -v 8848 |grep -v 1521 |grep -v tcp6 |grep -v :22 |grep 10.110.139.230
tcp        0      0 10.110.136.50:3508      10.110.139.230:5200     ESTABLISHED 3872246/nginx: work  off (0.00/0/0)
tcp        0      0 10.110.136.50:31062     10.110.139.230:5200     TIME_WAIT   -                    timewait (51.06/0/0)
注意可以再次修改一下 端口信息再次進行驗證
sysctl -w "net.ipv4.ip_local_port_range=5000 5100"
測試結果爲: 
[root@KylinV10SP3ARM64 nginx]# netstat -anop |grep tcp |grep -v LISTEN |grep -v 637 |grep -v 8848 |grep -v 1521 |grep -v tcp6 |grep -v :22 |grep 10.110.139.230
tcp        0      0 10.110.136.50:5096      10.110.139.230:5200     ESTABLISHED 3872246/nginx: work  off (0.00/0/0)
tcp        0      0 10.110.136.50:3508      10.110.139.230:5200     TIME_WAIT   -                    timewait (55.94/0/0)
僅僅是執行了一下刷新動作. 
就會看到上面一個3508 local 的本地端口開始進入time_wait狀態
新建立的連接的local_port 就是 5096  
sysctl -w "net.ipv4.ip_local_port_range=5000 5050"
效果也是完全一致符合猜測. 
[root@KylinV10SP3ARM64 nginx]# netstat -anop |grep tcp |grep -v LISTEN |grep -v 637 |grep -v 8848 |grep -v 1521 |grep -v tcp6 |grep -v :22 |grep 10.110.139.230
tcp        0      0 10.110.136.50:5096      10.110.139.230:5200     TIME_WAIT   -                    timewait (56.10/0/0)
tcp        0      0 10.110.136.50:5008      10.110.139.230:5200     ESTABLISHED 3872246/nginx: work  off (0.00/0/0)

# 需要注意 修改改端口僅影響 第四列的本地連接信息, 不會影響第五列的外部連接信息
# 外部的需要是一個 監聽端口爲主. 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章