Tomcat 調優之從 Linux 內核源碼層面看 Tcp backlog

前兩天看到一群里在討論 Tomcat 參數調優,看到不止一個人說通過 accept-count 來配置線程池大小 , 我笑了笑,看來其實很多人并不太了解我們用的最多的 WebServer Tomcat,這篇文章就來聊下 Tomcat 調優,重點介紹下線程池調優及 TCP 半連接、全連接隊列調優 。
Tomcat 線程池先來說下線程池調優,就拿 SpringBoot 內置的 Tomcat 來說 , 確實是支持線程池參數配置的,但不是 accept-count 參數 , 可以通過 threads.max 和 threads.minSpare 來配置線程池最大線程數和核心線程數 。
如果沒有設置,則會使用默認值
threads.max: 200threads.minSpare: 10Tomcat 底層用到的 ThreadPoolExecutor 也不是 JUC 原生的線程池 , 而是自定義的,做了一些調整來支持 IO 密集型場景使用,具體介紹可以看之前寫的兩篇文章 。
動態線程池(DynamicTp),動態調整 Tomcat、Jetty、Undertow 線程池參數篇
以面試官視角萬字解讀線程池 10 大經典面試題!
通過這兩篇文章能了解到 Tomcat 自定義線程池的執行流程及原理,然后可以接入動態線程池框架 DynamicTp,將 Tomcat 線程池交由 DynamicTp 管理,使之能享受到動態調參、監控告警的功能 。
在配置中心配置 tomcat 線程池核心參數
spring:dynamic:tp:tomcatTp:corePoolSize: 100maximumPoolSize: 400keepAliveTime: 60Tomcat 線程池調優主要思想就是動態化線程池參數,上線前通過壓測初步確定一套較優的參數值,上線后通過監控、告警實時感知線程池負載情況,動態調整參數適應流量的變化 。
【Tomcat 調優之從 Linux 內核源碼層面看 Tcp backlog】線程池調優就說這些吧,下面主要介紹下 Tcp backlog 及半連接、全連接隊列相關內容 。
劃重點

  1. threads.max 和 threads.minSpare 是用來配置 Tomcat 的工作線程池大小的,是線程池維度的參數
  2. accept-count 和 max-connections 是 TCP 維度的配置參數
TCP 狀態機Client 端和 Server 端基于 TCP 協議進行通信時,首先需要經過三次握手建連的,通信結束時需要通過四次揮手斷連的 。注意所謂的連接其實是個邏輯上的概念 , 并不存在真實連接的,那 TCP 是怎么面向連接傳輸的呢?
TCP 定義了個復雜的有限狀態機模型,通信雙方通過維護一個連接狀態 , 來達到看起來像有一條連接的效果 。如下是 TCP 狀態機狀態流轉圖,這個圖非常重要,建議大家一定要掌握 。圖片來自 TCP 狀態機
  1. 圖上半部分描述了三次握手建立連接過程中狀態的變化
  2. 圖下半部分描述了四次揮手斷開連接過程中狀態的變化

Tomcat 調優之從 Linux 內核源碼層面看 Tcp backlog

文章插圖
圖 2 是通過三次握手建立連接的過程,老八股文了,建議結合圖 1 狀態機變化圖看 , 圖片來源三次握手
Tomcat 調優之從 Linux 內核源碼層面看 Tcp backlog

文章插圖
圖 3 是通過四次揮手斷開連接的過程,建議結合圖 1 狀態機變化圖看,圖片來源四次揮手
Tomcat 調優之從 Linux 內核源碼層面看 Tcp backlog

文章插圖
服務端程序調用 listen() 函數后,TCP 狀態機從 CLOSED 轉變為 LISTEN , 并且 linux 內核會創建維護兩個隊列 。一個是半連接隊列(Syn queue),另一個是全連接隊列(Accept queue) 。
建連主要流程如下:
  1. 客戶端向服務端發送 SYN 包請求建立連接,發送后客戶端進入 SYN_SENT 狀態
  2. 服務端收到客戶端的 SYN 請求 , 將該連接存放到半連接隊列(Syn queue)中,并向客戶端回復 SYN + ACK,隨后服務端進入 SYN_RECV 狀態
  3. 客戶端收到服務端的 SYN + ACK 后,回復服務端 ACK 并進入 ESTABLISHED 狀態
  4. 服務端收到客戶端的 ACK 后,從半連接隊列中取出連接放到全連接隊列(Accept queue)中 , 服務端進入 ESTABLISHED 狀態
  5. 服務端程序調用 accept() 方法 , 從全連接隊列中取出連接進行處理請求
連接隊列大小上述提到了半連接隊列、全連接隊列,這兩隊列都有大小限制的,超過的連接會被丟掉或者返回 RST 包 。
半連接隊列大小主要受:listen backlog、somaxconn、tcp_max_syn_backlog 這三參數影響
全連接隊列大小主要受:listen backlog 和 somaxconn 這兩參數影響
tcp_max_syn_backlog 和 somaxconn 都是 linux 內核參數,在 /proc/sys/net/ipv4/ 和 /proc/sys/net/core/ 下,可以通過 /etc/sysctl.conf 文件來修改,默認值為 128 。

推薦閱讀