-------------------------------------------------------------------------------------------------------
打開linux-tcp端口快速回收
事件:
之前看到一些文章說關於流量升高導致TIME_WAIT增加,MySQL連接大量失敗的問題, 當時並不是很理解究竟怎么回事
今天在對阿里雲服務器上的tengine 做 1000個並發的webbench 測試時,ssh 會被踢掉,
懷疑網絡鏈接的問題 ,用netstat 查看 ,看到有很多很多 TIME_WAIT 狀態的 tcp 鏈接:
…
tcp 0 0 42.121.16.232:www 42.121.16.220:44091 TIME_WAIT
tcp 0 0 42.121.16.232:www 42.121.16.220:42309 TIME_WAIT
tcp 0 0 42.121.16.232:www 42.121.16.220:43896 TIME_WAIT
tcp 0 0 42.121.16.232:www 42.121.16.220:44150 TIME_WAIT
tcp 0 0 localhost:9000 localhost:34634 TIME_WAIT
tcp 0 0 42.121.16.232:www 42.121.16.220:44493 TIME_WAIT
tcp 0 0 localhost:9000 localhost:35354 TIME_WAIT
tcp 0 0 42.121.16.232:www 42.121.16.220:42770 TIME_WAIT
tcp 0 0 localhost:9000 localhost:34995 TIME_WAIT
tcp 0 0 localhost:9000 localhost:35038 TIME_WAIT
tcp 0 0 localhost:9000 localhost:34108 TIME_WAIT
tcp 0 0 42.121.16.232:www 42.121.16.220:41764 TIME_WAIT
tcp 0 0 42.121.16.232:www 42.121.16.220:42337 TIME_WAIT
tcp 0 0 42.121.16.232:www 42.121.16.220:44179 TIME_WAIT
…
nginx將php解析通過TCP轉發給php-fpm,需要占用一個TCP,php-fpm中的mysql連接, 又需要占用一個TCP
(但是檢查發現, 其實沒有 php-fpm -> mysql 的鏈接, 因為mysql使用的不是TCP而是UNIX SOCKET, 具體看 這里 )
再看:
~# netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
SYN_RECV 186
TIME_WAIT 30245
ESTABLISHED 211
FIN_WAIT1 333
TIME_WAIT 居然有3W多個 ,隨着時間推移還會極速增加中
怪不得了, 端口也就65536個, 用完了自然就沒了!!
而且,
解決辦法:打開LINUX TCP 端口快速回收
修改 /etc/sysctl.conf, 添加兩條數據
#打開重用
net.ipv4.tcp_tw_reuse = 1
#打開快速回收
net.ipv4.tcp_tw_recycle = 1
保存后執行 sysctl -p 生效
注:
如果nginx,php-fpm,mysql都在同一台機器, 推薦php-fpm和mysql都使用UNIX SOKCET. 方法看 這里
TIME_WAIT產生原因:
1、nginx現有的負載均衡模塊實現php fastcgi負載均衡,nginx使用了短連接方式,所以會造成大量處於TIME_WAIT狀態的連接。
2、TCP/IP設計者本來是這么設計的, 主要有兩個原因
(1) 防止上一次連接中的包,迷路后重新出現,影響新連接(經過2MSL,上一次連接中所有的重復包都會消失)
(2) 可靠的關閉TCP連接, 在主動關閉方發送的最后一個 ack(fin) ,有可能丟失,這時被動方會重新發fin, 如果這時主動方處於 CLOSED 狀態 ,就會響應 rst 而不是 ack。所以主動方要處於 TIME_WAIT 狀態,而不能是 CLOSED 。
為什么短連接TCP在高並發大流量會扛不住?
一般LNMP服務器架構, 都是nginx接受http請求, 然后將php文件的解析轉發給php-fpm, 這個過程nginx需要使用新的TCP端口與php-fpm的9000端口去建立TCP鏈接, 那么, 一個php請求就需要一個新的端口
若2MSL時間為1分鍾以上,同時,不同用戶http兩次請求間隔很短。那么反代的端口,5秒用1W個,10秒2W,15秒3W,20秒4W,25秒5W,30秒6W!!!而linux最大端口就是65535個, 前面已經用掉的端口還沒被回收掉。那么將會有很多的用戶請求被nginx接收之后,因沒有端口資源而無法與php-fpm創建tcp連接… 所以服務器會’掛掉’
