timewait並不是多餘的。在tcp協議被創造,經歷了大量的實際場景實踐之後,timewait出現了,因為tcp主動關閉連線的一方需要timewait狀態,它是我們的朋友。這是《unix網路程式設計》的作者----steven對timewait的態度。
tcp要保證在所有可能的情況下使得所有的資料都能夠被正確送達。當你關閉乙個socket時,主動關閉一端的socket將進入time_wait狀態,而被動關閉一方則轉入closed狀態,這的確能夠保證所有的資料都被傳輸。當乙個socket關閉的時候,是通過兩端四次握手完成的,當一端呼叫close()時,就說明本端沒有資料要傳送了。這好似看來在握手完成以後,socket就都可以處於初始的closed狀態了,其實不然。原因是這樣安排狀態有兩個問題, 首先,我們沒有任何機制保證最後的乙個ack能夠正常傳輸,第二,網路上仍然有可能有殘餘的資料報(wandering duplicates),我們也必須能夠正常處理。
timewait就是為了解決這兩個問題而生的。
1.假設最後乙個ack丟失了,被動關閉一方會重發它的fin。主動關閉一方必須維持乙個有效狀態資訊(timewait狀態下維持),以便能夠重發ack。如果主動關閉的socket不維持這種狀態而進入closed狀態,那麼主動關閉的socket在處於closed狀態時,接收到fin後將會響應乙個rst。被動關閉一方接收到rst後會認為出錯了。如果tcp協議想要正常完成必要的操作而終止雙方的資料流傳輸,就必須完全正確的傳輸四次握手的四個節,不能有任何的丟失。這就是為什麼socket在關閉後,仍然處於time_wait狀態的第乙個原因,因為他要等待以便重發ack。
2.假設目前連線的通訊雙方都已經呼叫了close(),雙方同時進入closed的終結狀態,而沒有走time_wait狀態。會出現如下問題,現在有乙個新的連線被建立起來,使用的ip位址與埠與先前的完全相同,後建立的連線是原先連線的乙個完全復用。還假定原先的連線中有資料報殘存於網路之中,這樣新的連線收到的資料報中有可能是先前連線的資料報。為了防止這一點,tcp不允許新連線復用time_wait狀態下的socket。處於time_wait狀態的socket在等待兩倍的msl時間以後(之所以是兩倍的msl,是由於msl是乙個資料報在網路中單向發出到認定丟失的時間,乙個資料報有可能在傳送途中或是其響應過程中成為殘餘資料報,確認乙個資料報及其響應的丟棄的需要兩倍的msl),將會轉變為closed狀態。這就意味著,乙個成功建立的連線,必然使得先前網路中殘餘的資料報都丟失了。
timewait既友好,又令人頭疼。
但是我們還是要抱著乙個友好的態度來看待它,因為它盡它的能力保證了伺服器的健壯性。
1. linux沒有在sysctl或者proc檔案系統暴露修改這個timewait超時時間的介面,可以修改核心協議棧**中關於這個timewait的超時時間引數,重編核心,讓它縮短超時時間,加快**;
2. 利用so_linger選項的強制關閉方式,發rst而不是fin,來越過timewait狀態,直接進入closed狀態。詳見我的博文《tcp之選項
so_linger
》。sysctl改兩個核心引數就行了,如下:
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
簡單來說,就是開啟系統的timewait重用和快速**,至於怎麼重用和快速**,這個問題我沒有深究,實際場景中這麼做確實有效果。用netstat或者ss觀察就能得出結論。
還有些朋友同時也會開啟syncookies這個功能,如下:
net.ipv4.tcp_syncookies = 1
開啟這個syncookies的目的實際上是:「在伺服器資源(並非單指埠資源,拒絕服務有很多種資源不足的情況)不足的情況下,盡量不要拒絕tcp的syn(連線)請求,盡量把syn請求快取起來,留著過會兒有能力的時候處理這些tcp的連線請求」。
如果併發量真的非常非常高,開啟這個其實用處不大。
http各種中的各種timeout
1.tomcat 可以通過telnet測試 在tomcat的server.xml中,有個配置節 uriencoding utf 8 其中的connectiontimeout代表的意思是 在已經建立的http連線上,如果5000毫秒沒有資訊傳輸,怎伺服器關閉連線。但如果tomcat伺服器內容消耗的時間...
Linux 中 的程序
1.fork 與vfork 的區別 vfork 使用中父子程序共享虛擬記憶體空間,fork 則不是 vfork保證子程序先執行 而fork的父子程序執行順序是不定的,它取決於核心的排程演算法 example 1 include include include int main else printf...
Linux中僵死程序
僵死程序 殭屍程序 一 僵死程序產生的原因 用fork建立程序,子程序終止時,它與父程序之間還會保持聯絡,知道父程序也正常終止或者父程序呼叫 wait 才結束,所以程序表中子程序的表項不會立即釋放,因為它的退出碼還需要儲存起來,以備父程序 wait 呼叫的時候使用。子程序先於父程序結束,父程序沒有獲...