https://jaminzhang.github.io/linux/understand-Linux-backlog-and-somaxconn-kernel-arguments/
各參數的含義:https://www.alibabacloud.com/help/zh/faq-detail/41334.htm
理解 Linux backlog/somaxconn 內核參數
理解 Linux backlog/somaxconn 內核參數
引言
之前負載均衡超時問題這篇博文中提到一個可能原因是:
后端服務器 Socket accept 隊列滿,系統的 somaxconn 內核參數默認太小。
下面我們我深入學習理解下 somaxconn 內核參數相關內容。
TCP SYN_REVD, ESTABELLISHED 狀態對應的隊列
TCP 建立連接時要經過 3 次握手,在客戶端向服務器發起連接時, 對於服務器而言,一個完整的連接建立過程,服務器會經歷 2 種 TCP 狀態:SYN_REVD, ESTABELLISHED。 對應也會維護兩個隊列: 1. 一個存放 SYN 的隊列(半連接隊列) 2. 一個存放已經完成連接的隊列(全連接隊列) 當一個連接的狀態是 SYN RECEIVED 時,它會被放在 SYN 隊列中。 當它的狀態變為 ESTABLISHED 時,它會被轉移到另一個隊列。 所以后端的應用程序只從已完成的連接的隊列中獲取請求。 如果一個服務器要處理大量網絡連接,且並發性比較高,那么這兩個隊列長度就非常重要了。 因為,即使服務器的硬件配置非常高,服務器端程序性能很好, 但是這兩個隊列非常小,那么經常會出現客戶端連接不上的現象, 因為這兩個隊列一旦滿了后,很容易丟包,或者連接被復位。 所以,如果服務器並發訪問量非常高,那么這兩個隊列的設置就非常重要了。
Linux backlog 參數意義
對於 Linux 而言,基本上任意語言實現的通信框架或服務器程序在構造 socket server 時,都提供了 backlog 這個參數, 因為在監聽端口時,都會調用系統底層 API: int listen(int sockfd, int backlog); listen 函數中 backlog 參數的定義如下: Now it specifies the queue length for completely established sockets waiting to be accepted, instead of the number of incomplete connection requests. The maximum length of the queue for incomplete sockets can be set using the tcp_max_syn_backlog sysctl. When syncookies are enabled there is no logical maximum length and this sysctl setting is ignored. If the socket is of type AF_INET, and the backlog argument is greater than the constant SOMAXCONN(128 default), it is silently truncated to SOMAXCONN. backlog 參數描述的是服務器端 TCP ESTABELLISHED 狀態對應的全連接隊列長度。 全連接隊列長度如何計算? 如果 backlog 大於內核參數 net.core.somaxconn,則以 net.core.somaxconn 為准, 即全連接隊列長度 = min(backlog, 內核參數 net.core.somaxconn),net.core.somaxconn 默認為 128。 這個很好理解,net.core.somaxconn 定義了系統級別的全連接隊列最大長度, backlog 只是應用層傳入的參數,不可能超過內核參數,所以 backlog 必須小於等於 net.core.somaxconn。 半連接隊列長度如何計算? 半連接隊列長度由內核參數 tcp_max_syn_backlog 決定, 當使用 SYN Cookie 時(就是內核參數 net.ipv4.tcp_syncookies = 1),這個參數無效, 半連接隊列的最大長度為 backlog、內核參數 net.core.somaxconn、內核參數 tcp_max_syn_backlog 的最小值。 即半連接隊列長度 = min(backlog, 內核參數 net.core.somaxconn,內核參數 tcp_max_syn_backlog)。 這個公式實際上規定半連接隊列長度不能超過全連接隊列長度。 其實,對於 Nginx/Tomcat 等這種 Web 服務器,都提供了 backlog 參數設置入口, 當然它們都會有默認值,通常這個默認值都不會太大(包括內核默認的半連接隊列和全連接隊列長度)。 如果應用並發訪問非常高,只增大應用層 backlog 是沒有意義的,因為可能內核參數關於連接隊列設置的都很小, 一定要綜合應用層 backlog 和內核參數一起看,通過公式很容易調整出正確的設置。
linux中tcp連接內核參數調優somaxconn
https://blog.csdn.net/jackyechina/article/details/70992308
永久生效:
vim /etc/sysctl.conf
net.core.somaxconn=32768
sysctl -p
立即生效:
sysctl -w net.core.somaxconn=32768
重啟應用生效
sysctl -a顯示所有內核參數
看其解析:
對於一個TCP連接,Server與Client需要通過三次握手來建立網絡連接.當三次握手成功后,
我們可以看到端口的狀態由LISTEN轉變為ESTABLISHED,接着這條鏈路上就可以開始傳送數據了.
每一個處於監聽(Listen)狀態的端口,都有自己的監聽隊列.監聽隊列的長度,與如下兩方面有關:
- somaxconn參數.
- 使用該端口的程序中listen()函數.
關於somaxconn參數:
定義了系統中每一個端口最大的監聽隊列的長度,這是個全局的參數,默認值為128.限制了每個端口接收新tcp連接偵聽隊列的大小。
對於一個經常處理新連接的高負載 web服務環境來說,默認的 128 太小了。大多數環境這個值建議增加到 1024 或者更多。
服務進程會自己限制偵聽隊列的大小(例如 sendmail(8) 或者 Apache),常常在它們的配置文件中有設置隊列大小的選項。大的偵聽隊列對防止拒絕服務 DoS 攻擊也會有所幫助。