TCP/IP面試相關問題

第一次握手:建立連接時,客戶端發送syn包(syn=x)到服務器,並進入SYN_SENT狀態,等待服務器確認;SYN:同步序列編號(Synchronize Sequence Numbers)。

第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;

第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手。

 

第一次握手:建立連接時,客戶端發送syn包(syn=x)到服務器,並進入SYN_SENT狀態,等待服務器確認;SYN:同步序列編號(Synchronize Sequence Numbers)。

第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;

第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手。

 

 

 

 

所有執行主動關閉的socket都會進入TIME_WAIT狀態主動關閉的一方在發送最後一個 ack 後就會進入 TIME_WAIT 狀態 停留2MSL(max segment lifetime)時間,這個是TCP/IP必不可少的,也就是“解決”不了的。 

1。防止上一次連接中的包,迷路後重新出現,影響新連接(經過2MSL,上一次連接中所有的重複包都會消失) 
2。可靠的關閉TCP連接 
在主動關閉方發送的最後一個 ack(fin) ,有可能丟失,這時被動方會重新發fin, 如果這時主動方處於 CLOSED 狀態 ,就會響應 rst 而不是 ack。所以主動方要處於 TIME_WAIT 狀態,而不能是 CLOSED 。

 

所以在大併發服務器編程中,儘量設計成客戶端主動斷開連接,而不是由服務器端斷開。

 

可以在 /etc/sysctl.conf 設置一些內核參數,讓內核儘快回收處理TIME_WAIT狀態,以免因爲這此佔用端口過多(端口不夠用就是文件描述符不夠用了,因爲文件描述符只有在從TIME_WAIT狀態轉換到CLOSE狀態後纔會真正被系統收回。還有一個是),影響正常的客戶請求連接。

 

net.ipv4.tcp_syncookies = 1 表示開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少量SYN攻擊,默認爲0,表示關閉; 
net.ipv4.tcp_tw_reuse = 1 表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉; 
net.ipv4.tcp_tw_recycle = 1 表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉。 
net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。 
net.ipv4.tcp_keepalive_time = 1200 表示當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時,改爲20分鐘。 
net.ipv4.ip_local_port_range = 1024 65000 表示用於向外連接的端口範圍。缺省情況下很小:32768到61000,改爲1024到65000。 
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN隊列的長度,默認爲1024,加大隊列長度爲8192,可以容納更多等待連接的網絡連接數。 
net.ipv4.tcp_max_tw_buckets = 5000表示系統同時保持TIME_WAIT套接字的最大數量,如果超過這個數字,TIME_WAIT套接字將立刻被清除並打印警告信息。默認爲 180000,改爲5000。對於Apache、Nginx等服務器,上幾行的參數可以很好地減少TIME_WAIT套接字數量,但是對於Squid,效 果卻不大。此項參數可以控制TIME_WAIT套接字的最大數量,避免Squid服務器被大量的TIME_WAIT套接字拖死。 
執行以下命令使配置生效: 
/sbin/sysctl -p

 

 

 

爲什麼我們要關注這個高併發短連接呢?有兩個方面需要注意:
1. 高併發可以讓服務器在短時間範圍內同時佔用大量端口,而端口有個0~65535的範圍,並不是很多,刨除系統和其他服務要用的,剩下的就更少了。
2. 在這個場景中,短連接表示“業務處理+傳輸數據的時間 遠遠小於 TIMEWAIT超時的時間”的連接

      這裏有個相對長短的概念,比如取一個web頁面,1秒鐘的http短連接處理完業務,在關閉連接之後,這個業務用過的端口會停留在TIMEWAIT狀態幾分鐘,而這幾分鐘,其他HTTP請求來臨的時候是無法佔用此端口的(佔着茅坑不拉翔)。單用這個業務計算服務器的利用率會發現,服務器幹正經事的時間和端口(資源)被掛着無法被使用的時間的比例是 1:幾百,服務器資源嚴重浪費。(說個題外話,從這個意義出發來考慮服務器性能調優的話,長連接業務的服務就不需要考慮TIMEWAIT狀態。同時,假如你對服務器業務場景非常熟悉,你會發現,在實際業務場景中,一般長連接對應的業務的併發量並不會很高
     綜合這兩個方面,持續的到達一定量的高併發短連接,會使服務器因端口資源不足而拒絕爲一部分客戶服務。同時,這些端口都是服務器臨時分配,無法用SO_REUSEADDR選項解決這個問題。

 

大量的TIMEWAIT狀態影響服務器後續的連接請求服務,目前按我理解應該只在有中間代理中轉服務器時纔會出現這種情況,因爲中轉中間層的服務器IP地址有限(一般只有1~10臺),這樣很容易出現客戶端下次連接的請求與處於TIMEWAIT狀態的客戶端IP和端口號一樣,導致不能正常響應客戶端的連接請求。在TIMEWAIT狀態同樣的客戶端IP和端口號連接過來時,服務器可能直接發送RST報文拒絕連接服務。

 

 

所有執行主動關閉的socket都會進入TIME_WAIT狀態,主動關閉的一方在發送最後一個 ack 後就會進入 TIME_WAIT 狀態 停留2MSL(max segment lifetime)時間,這個是TCP/IP必不可少的,也就是“解決”不了的。 

1。防止上一次連接中的包,迷路後重新出現,影響新連接(經過2MSL,上一次連接中所有的重複包都會消失) 
2。可靠的關閉TCP連接 
在主動關閉方發送的最後一個 ack(fin) ,有可能丟失,這時被動方會重新發fin, 如果這時主動方處於 CLOSED 狀態 ,就會響應 rst 而不是 ack。所以主動方要處於 TIME_WAIT 狀態,而不能是 CLOSED 。

 

所以在大併發服務器編程中,儘量設計成客戶端主動斷開連接,而不是由服務器端斷開。

 

可以在 /etc/sysctl.conf 設置一些內核參數,讓內核儘快回收處理TIME_WAIT狀態,以免因爲這此佔用端口過多(端口不夠用就是文件描述符不夠用了,因爲文件描述符只有在從TIME_WAIT狀態轉換到CLOSE狀態後纔會真正被系統收回。還有一個是),影響正常的客戶請求連接。

 

net.ipv4.tcp_syncookies = 1 表示開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少量SYN攻擊,默認爲0,表示關閉; 
net.ipv4.tcp_tw_reuse = 1 表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉; 
net.ipv4.tcp_tw_recycle = 1 表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉。 
net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。 
net.ipv4.tcp_keepalive_time = 1200 表示當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時,改爲20分鐘。 
net.ipv4.ip_local_port_range = 1024 65000 表示用於向外連接的端口範圍。缺省情況下很小:32768到61000,改爲1024到65000。 
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN隊列的長度,默認爲1024,加大隊列長度爲8192,可以容納更多等待連接的網絡連接數。 
net.ipv4.tcp_max_tw_buckets = 5000表示系統同時保持TIME_WAIT套接字的最大數量,如果超過這個數字,TIME_WAIT套接字將立刻被清除並打印警告信息。默認爲 180000,改爲5000。對於Apache、Nginx等服務器,上幾行的參數可以很好地減少TIME_WAIT套接字數量,但是對於Squid,效 果卻不大。此項參數可以控制TIME_WAIT套接字的最大數量,避免Squid服務器被大量的TIME_WAIT套接字拖死。 
執行以下命令使配置生效: 
/sbin/sysctl -p

 

 

 

爲什麼我們要關注這個高併發短連接呢?有兩個方面需要注意:
1. 高併發可以讓服務器在短時間範圍內同時佔用大量端口,而端口有個0~65535的範圍,並不是很多,刨除系統和其他服務要用的,剩下的就更少了。
2. 在這個場景中,短連接表示“業務處理+傳輸數據的時間 遠遠小於 TIMEWAIT超時的時間”的連接

      這裏有個相對長短的概念,比如取一個web頁面,1秒鐘的http短連接處理完業務,在關閉連接之後,這個業務用過的端口會停留在TIMEWAIT狀態幾分鐘,而這幾分鐘,其他HTTP請求來臨的時候是無法佔用此端口的(佔着茅坑不拉翔)。單用這個業務計算服務器的利用率會發現,服務器幹正經事的時間和端口(資源)被掛着無法被使用的時間的比例是 1:幾百,服務器資源嚴重浪費。(說個題外話,從這個意義出發來考慮服務器性能調優的話,長連接業務的服務就不需要考慮TIMEWAIT狀態。同時,假如你對服務器業務場景非常熟悉,你會發現,在實際業務場景中,一般長連接對應的業務的併發量並不會很高
     綜合這兩個方面,持續的到達一定量的高併發短連接,會使服務器因端口資源不足而拒絕爲一部分客戶服務。同時,這些端口都是服務器臨時分配,無法用SO_REUSEADDR選項解決這個問題。

 

大量的TIMEWAIT狀態影響服務器後續的連接請求服務,目前按我理解應該只在有中間代理中轉服務器時纔會出現這種情況,因爲中轉中間層的服務器IP地址有限(一般只有1~10臺),這樣很容易出現客戶端下次連接的請求與處於TIMEWAIT狀態的客戶端IP和端口號一樣,導致不能正常響應客戶端的連接請求。在TIMEWAIT狀態同樣的客戶端IP和端口號連接過來時,服務器可能直接發送RST報文拒絕連接服務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章