天天看點

TCP/IP協定中backlog參數

TCP/IP協定中backlog分析與設定以及TCP狀态變化

TCP/IP協定卷一中是有說明設定backlog這個值的,這值是做什麼的呢?

大家都知道TCP建立連接配接時是要進行三次握手連接配接的,但是否三次握手完成了,服務端就進行處理了(accept)呢,如果沒有處理就變成什麼情況,假如沒有及時accept的話,後續用戶端就連接配接不上或連接配接失敗。這樣就談不上吞吐量了。想必大家也認為TCP不是那麼設計的。

backlog其實是一個連接配接隊列,以下是backlog隊列大小公式。

backlog隊列總和=未完成三次握手隊列 +  已經完成三次握手隊列

以上參數解釋說明如下:

未完成三次握手隊列:伺服器處于listen狀态時收到用戶端syn 封包(connect)時放入未完成隊列中。

已經完成三次握手隊列:三次握手的第二個狀态即伺服器syn+ ack響應client後,此時第三個狀态ack封包到達前(用戶端對伺服器syn的ack)一直保留在未完成連接配接隊列中,如果三次握手完成,該條目将從未完成連接配接隊列搬到已完成連接配接隊列尾部.

backlog參數設定既可以在linux核心參數設定(修改檔案/etc/sysctl相關參數),也可以在socket系統調用listen函數時設定(第二個參數),這二者差別是,前者為全局性的,影響所有socket,後者為局部性的,影響目前socket。

  TCP建立連接配接是要進行三次握手,但是否完成三次握手後,伺服器就處理(accept)呢?

  backlog其實是一個連接配接隊列,在Linux核心2.2之前,backlog大小包括半連接配接狀态和全連接配接狀态兩種隊列大小。

  半連接配接狀态為:伺服器處于Listen狀态時收到用戶端SYN封包時放入半連接配接隊列中,即SYN queue(伺服器端口狀态為:SYN_RCVD)。

  全連接配接狀态為:TCP的連接配接狀态從伺服器(SYN+ACK)響應用戶端後,到用戶端的ACK封包到達伺服器之前,則一直保留在半連接配接狀态中;當伺服器接收到用戶端的ACK封包後,該條目将從半連接配接隊列搬到全連接配接隊列尾部,即 accept queue (伺服器端口狀态為:ESTABLISHED)。

  在Linux核心2.2之後,分離為兩個backlog來分别限制半連接配接(SYN_RCVD狀态)隊列大小和全連接配接(ESTABLISHED狀态)隊列大小。

  SYN queue 隊列長度由 /proc/sys/net/ipv4/tcp_max_syn_backlog 指定,預設為2048。

  Accept queue 隊列長度由 /proc/sys/net/core/somaxconn 和使用listen函數時傳入的參數,二者取最小值。預設為128。在Linux核心2.4.25之前,是寫死在代碼常量 SOMAXCONN ,在Linux核心2.4.25之後,在配置檔案 /proc/sys/net/core/somaxconn 中直接修改,或者在 /etc/sysctl.conf 中配置 net.core.somaxconn = 128 。

TCP/IP協定中backlog參數
  可以通過ss指令來顯示
TCP/IP協定中backlog參數

[root@localhost ~]# ss -l
State       Recv-Q Send-Q                                     Local Address:Port                                         Peer Address:Port     
LISTEN      0      128                                                    *:http                                                    *:*       
LISTEN      0      128                                                   :::ssh                                                    :::*       
LISTEN      0      128                                                    *:ssh                                                     *:*       
LISTEN      0      100                                                  ::1:smtp                                                   :::*       
LISTEN      0      100                                            127.0.0.1:smtp                                                    *:*             
TCP/IP協定中backlog參數

  在LISTEN狀态,其中 Send-Q 即為Accept queue的最大值,Recv-Q 則表示Accept queue中等待被伺服器accept()。

  另外用戶端connect()傳回不代表TCP連接配接建立成功,有可能此時accept queue 已滿,系統會直接丢棄後續ACK請求;用戶端誤以為連接配接已建立,開始調用等待至逾時;伺服器則等待ACK逾時,會重傳SYN+ACK 給用戶端,重傳次數受限 net.ipv4.tcp_synack_retries ,預設為5,表示重發5次,每次等待30~40秒,即半連接配接預設時間大約為180秒,該參數可以在tcp被洪水攻擊是臨時啟用這個參數。

  檢視SYN queue 溢出

[root@localhost ~]# netstat -s | grep LISTEN
102324 SYNs to LISTEN sockets dropped      

  檢視Accept queue 溢出

[root@localhost ~]# netstat -s | grep TCPBacklogDrop
TCPBacklogDrop: 2334