最近同事遇到一個問題,使用python開發的工具在執行的時候無法和MySQL建立串連,其最直接的現象就是滿篇的TIME_WAIT,最後通過調整tcp_timestamps參數問題得以解決,再次記錄一下這次解決的經驗總結。
ps:不過先汗顏一個,對基礎的tcp知識太不敏感了,需要回爐重新學習啊。
大家都知道建立串連是著名的三向交握機制。
那麼如何關閉串連呢? 其實也是著名的四次握手機制。
TIME_WAIT就產生在四次握手的的主動關閉方,而server端會進入close狀態。
那麼TIME_WAIT什麼時候會消失呢?LINUX會在2MSL時間內消失。(MSL是最大分段生存期,預設為2分鐘)
二、無法建立串連的原因
由於同事的指令碼的用途是進行採集資料後的寫入操作,為了加快速度故使用python的map功能並發寫入資料庫,當在指令碼執行的伺服器上報錯後,發現滿篇都是TIME_WAIT的現象。
經過我們內部討論,初步認為是由於TIME_WAT沒有快速回收導致Linux的可用連接埠被沾滿導致無發建立串連,和MySQL的設定沒有關係。
查看目前Linux可用連接埠範圍:
[me]sysctl -a|=
查看當前佔用的連接埠直接用netstat就可以了:
netstat -nat| -i time_wait| -l
三、如何解決?
對於TCP連結的最佳化大家都知道的三個參數:tcp_tw_reuse、tcp_tw_recycle、tcp_timestamp
1、我們先看看這3個參數的定義和作用。
tcp_tw_reuse:用來使用time-wait狀態的sockets重用
Allow to reuse TIME-WAIT sockets for new connections when it is
safe from protocol viewpoint. Default value is 0.It should not be changed without advice/request of technical experts.
tcp_tw_recycle:用來加速對time-wait
Enable fast recycling TIME-WAIT sockets. Default value is /
tcp_timestamp:在TCP的包頭新增時間戳記
Enable timestamps as defined RFC1323
2、調整記錄
我們先查看伺服器的狀態,發現reuse和recycle的參數都是1,但是time_wait並沒有被很快的回收,也沒有被快速的重用。
[root ~]# /proc/sys/net/ipv4/~]# /proc/sys/net/ipv4/
後來發現是由於tcp_timestamp這個參數設定為0的原因
[root ~] /proc/sys/net/ipv4/
將這個參數置為1之後,time_wati的狀態立刻下降了很多,指令碼也可以正常執行了。看來tcp_timestamp非常關鍵。
3、探尋原因
但是,究竟是tcp_tw_reuse起作用了? 還是tcp_tw_recycle起作用了?我們還是不知道,只能從現象得知問題解決了。
我們將tcp_tw_recycle的值設定為0之後,再次測試,再次出現了大量的time_wait現象。
為了證明tcp_tw_recycle真正起作用了,我們再次將tcp_tw_reuse參數設定為1,這時候也再次出現了大量的time_wait的現象。
看來,最終我們的結論是同時開啟tcp_tw_recycle,tcp_tw_reuse和tcp_timestamp才能真正做到快速回收和服用time-wait狀態的socket。
從stackoverflow上看到的一個答案比較靠譜。點這裡
但是同時也發現,網上有很多資訊顯示,如果同時開啟tcp_tw_recycle和tcp_timestamp會出現問題。主要是由於TCP的一種行為
RFC 1323 TCP Extensions for High Performance Jacobson, Braden, & Borman
An additional mechanism could be added to the TCP,,
https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
http://lxr.free-electrons.com/source/net/ipv4/tcp_minisocks.c#L92
http://www.ietf.org/rfc/rfc1323.txt