天天看點

backlog配置_Nginx backlog配置概述

一、TCP 3次握手

可分為4步

1 用戶端發起connect(),發送SYN j

2 伺服器從SYN queue中建立條目,響應SYN k, ACK J+1

3 用戶端connect()成功傳回,響應ACK K+1

4 伺服器将socket從SYN queue移入accept queue,accept()成功傳回

注:SYN/FIN各占一個序列号,ACK/RST不占序列号

listen address[:port] [backlog=number],參數backlog 限制了用于存放處于挂起狀态連接配接的隊列最大長度, 已連接配接但未進行accept處理的SOCKET隊列大小,即這些連接配接已經完全建立了,但還沒有被處理,其預設值是 -1。當一個連接配接請求到達時,如果此時隊列滿了,用戶端會收到連接配接拒絕(“Connection refused”)。

php-fpm的backlog大小設定跟php-fpm的處理能力有關

1、backlog太大了,導緻php-fpm處理不過來,nginx那邊等待逾時,斷開連接配接,報504 gateway timeout錯。同時php-fpm處理完準備write 資料給nginx時,發現TCP連接配接斷開了,報“Broken pipe”。

2、php-fpm的backlog太小的話,nginx之類的client請求,根本進入不了php-fpm的accept queue,報“502 Bad Gateway”錯。是以,這還得去根據php-fpm的QPS來決定backlog的大小。計算方式最好為QPS=backlog。

SYN queue長度由tcp_max_syn_backlog指定,accept queue則由net.core.somaxconn決定,listen(fd, backlog)的backlog上限由somaxconn決定.

backlog=number

sets the backlog parameter in the listen() call that limits the maximum length for the queue of pending connections. By default, backlog is set to -1 on FreeBSD, DragonFly BSD, and macOS, and to 511 on other platforms.

backlog配置_Nginx backlog配置概述

在linux 2.2以前,backlog大小包括了半連接配接狀态和全連接配接狀态兩種隊列大小。linux 2.2以後,分離為兩個backlog來分别限制半連接配接SYN_RCVD狀态的未完成連接配接隊列大小跟全連接配接ESTABLISHED狀态的已完成連接配接隊列大小。

網際網路上常見的TCP SYN FLOOD惡意DOS攻擊方式就是用/proc/sys/net/ipv4/tcp_max_syn_backlog來控制的。

在使用listen函數時,核心會根據傳入參數的backlog跟系統配置參數/proc/sys/net/core/somaxconn中,二者取最小值,作為“ESTABLISHED狀态之後,完成TCP連接配接,等待服務程式ACCEPT”的隊列大小。在kernel 2.4.25之前,是寫死在代碼常量SOMAXCONN,預設值是128。在kernel 2.4.25之後,在配置檔案/proc/sys/net/core/somaxconn(即 /etc/sysctl.conf 之類 )中可以修改。

用戶端connect()傳回不代表TCP連接配接建立成功,有可能此時伺服器accept queue已滿,OS會直接丢棄後續ACK請求;

用戶端以為連接配接已建立,開始後續調用(譬如send)等待直至逾時;

伺服器則等待ACK逾時,會重傳SYN k, ACK J+1給用戶端(重傳次數受限net.ipv4.tcp_synack_retries);

注:accept queue溢出,即便SYN queue沒有溢出,新連接配接請求的SYN也可能被drop

二、How TCP backlog works in linux

在How TCP backlog works in linux一文中,作者給出了比較詳細的分析:

1、第一種實作方式

在底層維護一個由backlog指定大小的隊列。服務端收到SYN後,傳回一個SYN/ACK,并把連接配接放入隊列中,此時這個連接配接的狀态是SYN_RECEIVED。當用戶端傳回ACK後,此連接配接的狀态變為ESTABLISHED。隊列中隻有ESTABLISHED狀态的連接配接能夠交由應用處理。第一種實作方式可以簡單概括為:一個隊列,兩種狀态。

2、第二種實作方式

在底層維護一個SYN_RECEIVED隊列和一個ESTABLISHED隊列,當SYN_RECEIVED隊列中的連接配接傳回ACK後,将被移動到ESTABLISHED隊列中。backlog指的是ESTABLISHED隊列的大小。

傳統的基于BSD的tcp實作第一種方式,在linux2.2之前,核心也實作第一種方式。當隊列滿了以後,服務端再收到SYN時,将不會傳回SYN/ACK。比較優雅的處理方法就是不處理這條連接配接,不傳回RST,讓用戶端重試。

在linux2.2後,選擇第二種方式實作,SYN_RECEIVED隊列的大小由/proc/sys/net/ipv4/tcp_max_syn_backlog系統參數指定,ESTABLISHED隊列由backlog和/proc/sys/net/core/somaxconn中較小的指定。

三、如何檢視accept queue溢出:

netstat –s | grep LISTEN傳回*** SYNS to LISTEN sockets ignored

參考