1. 程式人生 > >TCP(二)

TCP(二)

時間比較 設置 accept 利用 規則 大量 握手 斷開 現象

TCP半連接和全連接問題

TCP握手過程詳解

技術分享圖片

如上圖所示,關鍵部分:syns queue(半連接隊列)和accept queue(全連接隊列)

正常情況下的處理過程如下:

1)當server端收到client發送的SYN後,將連接相關信息放在syns queue中,並回復SYN+ACK;

2)當server端收到client發送的ACK後,將連接相關信息從syns queue中取出並放在accept queue中。

異常情況:

步驟2)中如果accept queue滿了,則根據tcp_abort_on_overflow指定的策略執行

  如果tcp_abort_on_overflow為0,server丟棄client發送的ack,並且在一段時間後再次發送syn+ack給client(即重新走握手的第二步),如果cilent的超時時間比較短,就會出現異常;重試次數由net.ipv4.tcp_synack_retries指定(centos默認5次);

  如果tcp_abort_on_overflow為1,server將發送一個reset給client,表示要廢掉這次握手過程和連接。此時client應該會出現connection reset by peer異常。

怎麽查看隊列是否滿?

netstat -s

  該命令查看每個協議的統計數據

netstat -s | egrep "listen"

  如果看到:XXXX times the listen queue of a socket overflowed 並且XXXX 值在不斷增加,就說明有全連接隊列偶爾滿了。

ss -lnt | grep port

State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 50 :::9188 :::*

其中Send-Q為監聽9188端口的全連接隊列最大為50,Recv-Q表示全連接隊列中和等待進入全連接的數量。

全連接隊列的大小取決於:min(backlog, somaxconn) . backlog是在socket創建的時候傳入的(Java Socket默認為50),somaxconn是一個os級別的系統參數

半連接隊列的大小取決於:max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog)。 不同版本的os會有些差異.

CLOSE-WAIT問題

什麽情況下會出現CLOSE-WAIT狀態

  在被動關閉連接時,已經收到對方發來的FIN(並發送了ACK),但還沒有發送自己的FIN時,處於CLOSE_WAIT狀態。

正常情況下該狀態持續的時間應該很短,出現大量close_wait的現象,主要原因是某種情況下對方關閉了socket鏈接,但是我方忙與讀或者寫,沒有關閉連接。

產生該問題的例子:https://blog.csdn.net/yu616568/article/details/44677985

  首先,我這邊的大部分請求都需要查詢數據庫,我的數據庫連接池設置的最大連接數是100,所以每一個請求創建了一個連接,等到100個請求就把連接池占滿了,但是處理servlet的那個線程並沒有釋放這個連接,於是接下來的請求再去創建數據庫連接的時候就會一直阻塞在那裏,這裏我所用的是DBCP作為連接池的,它的實現好像是使用apache的objectPool來實現的,如果沒有可用的連接對象會導致線程等待,好了,servlet由於得不到數據庫連接而阻塞了,這個客戶端的請求就一直等待,客戶端使用httpclient設置了5s的請求超時時間,那麽超時之後就會拋出異常,關閉連接,關閉連接導致客戶端發送了FIN報文,我這邊的TCP/IP返回了ACK報文,但是由於處理請求的線程還處於阻塞的狀態,所以當前的連接狀態時CLOSE_WAIT。

解決方法
基本的思想就是要檢測出對方已經關閉的socket,然後關閉它

1.代碼需要判斷socket,一旦read返回0,斷開連接,read返回負,檢查一下errno,如果不是AGAIN,也斷開連接。(註:在UNP 7.5節的圖7.6中,可以看到使用select能夠檢測出對方發送了FIN,再根據這條規則就可以處理CLOSE_WAIT的連接)
2.給每一個socket設置一個時間戳last_update,每接收或者是發送成功數據,就用當前時間更新這個時間戳。定期檢查所有的時間戳,如果時間戳與當前時間差值超過一定的閾值,就關閉這個socket。
3.使用一個Heart-Beat線程,定期向socket發送指定格式的心跳數據包,如果接收到對方的RST報文,說明對方已經關閉了socket,那麽我們也關閉這個socket。
4.設置SO_KEEPALIVE選項,並修改內核參數

TCP協議在帶寬利用率、性能方面的優化

delay ack

  

Nagle算法

參考資料

服務器TIME_WAIT和CLOSE_WAIT詳解和解決辦法

CLOSE_WAIT狀態的原因與解決方法

關於TCP 半連接隊列和全連接隊列

就是要你懂 TCP | 最經典的TCP性能問題

TCP(二)