天天看點

【Tomcat】Tomcat參數調優:連接配接數和并發數

Tomcat參數調優:連接配接數和并發數

    • 連接配接數
      • 實戰
    • 并發處理線程數 調整
      • 實戰
配置項 含義 預設 建議 注意 備注
ConnectionTimeout 連接配接逾時 20s 減少 與程式處理能力有關,處理能力越快設定短一點沒關系 到底多久提示請求逾時
maxThreads 處理連接配接的最大線程數(并發量) 200 增加 不是越大越好
acceptCount(backlog) 等待接受accept的請求數量限制 100 增加 socket參數,min(accept,/proc/sys/net/core/somaxconn) 超過Tomcat能接收的請求數以後,堆積在作業系統的數量
maxConnections 最大連接配接處理數 nio 1w apr 8192 不變 Tomcat能接收的請求限制

請求發到tomcat的順序:

【Tomcat】Tomcat參數調優:連接配接數和并發數

連接配接數

【Tomcat】Tomcat參數調優:連接配接數和并發數
【Tomcat】Tomcat參數調優:連接配接數和并發數

過程解析:

一個使用者請求過來,如果是windows作業系統,它首先進入一個隊列,我們的selector會監聽底層的事件通知,這個隊列就是accept queue,代表TCP的3次握手成功後就會進入到我們的accept queue隊列,selector就會收到通知;紅線那一部分開始就是Tomcat的範疇了,tomcat就是接受連接配接(請求),如果請求太多(超過accept+maxConnection),JVM就會崩掉;這1W個請求正在處理裡面,這個處理就是我們的線程數量;請求超過預設的1W個請求也就是maxConnection的其他請求就會堆積到作業系統的acceptCount那裡。這個參數就是控制堆積數量的,如果是windows系統的話,超過了這個堆積數量,Tomcat的maxConnection塞滿了,作業系統的TCP也塞滿了,那我們的伺服器就不會讓它再連接配接了;但是在Linux下面就不止有acceptCount,握手過程中還有一個SYN隊列(acceptCount是指握手完成了才會進入accept queue),我們一般不會去調整紅線前的作業系統的東西,因為那是屬于核心的。我們一般會去調maxConnection,但是他有1W個,也不怎麼會去調了,但什麼情況會去調呢?

  • 什麼時候需要調整connections?如何調整?
    • connections小于maxThread的時候;需要調大;最好是比預期的最高并發數要大20%; 反正是堆積到Tomcat的work處理線程池中(堆積占記憶體)。
    • 假如我們有5個CPU,我們開了有5個線程在執行處理,但是我們的連接配接數connection才3個,那麼我們就會浪費了2個CPU資源。實際上我們的處理能力還很強,但是我們沒有讓我們的請求進來了。
    • 假如我們現在做一個程式,并發量是5000的,那我們的connections就不能低于5000,而且還要比5000高個20%。
  • 什麼時候需要調整acceptCount?
    • 想要受理更多的使用者請求,卻又不想堆積到tomcat中,利用作業系統來高效的堆積,可以調整為最高并發數-connections
    • 實際上不需要調整,tomcat預設acceptCount100個,linux預設128;最好是連接配接控制交給應用程式,這樣友善管理。
    • 假如我們在tomcat中把acceptCount改成200,但是作業系統的128沒有改,但其實還是128.
      【Tomcat】Tomcat參數調優:連接配接數和并發數

實戰

【Tomcat】Tomcat參數調優:連接配接數和并發數
  • 先用linux伺服器來測試
    【Tomcat】Tomcat參數調優:連接配接數和并發數
    • 用jMeter發10個請求
      【Tomcat】Tomcat參數調優:連接配接數和并發數
【Tomcat】Tomcat參數調優:連接配接數和并發數

配置協定、請求IP、端口、請求方法、接口

【Tomcat】Tomcat參數調優:連接配接數和并發數
【Tomcat】Tomcat參數調優:連接配接數和并發數

然後啟動測試

【Tomcat】Tomcat參數調優:連接配接數和并發數

檢視結果樹,我們可以看每2個請求顯示請求成功。雖然我們設定了10個線程,但是隻設定了兩個連接配接connections,是以每次隻處理了兩個請求,其他的都堆積在linux作業系統的預設128中了,是以,我們換windows作業系統試試

【Tomcat】Tomcat參數調優:連接配接數和并發數

換windows作業系統

【Tomcat】Tomcat參數調優:連接配接數和并發數
【Tomcat】Tomcat參數調優:連接配接數和并發數

maxConnection=2

acceptCount=3

windows系統的話一次隻能接收5個請求(2個在處理,3個允許在windows作業系統堆積)是以其他5個就會被告知連接配接失敗

【Tomcat】Tomcat參數調優:連接配接數和并發數

并發處理線程數 調整

  • 線程太少,CPU使用率過低,程式的吞吐量變小,容易堆積
  • 線程太多,上下文頻繁切換,性能反而變低。
  • 線程數調成多少合适?
    • 場景代入:伺服器配置2核,不考慮記憶體問題。收到請求,java代碼執行耗時50ms,等待資料傳回50ms
    • 理想的線程數量=(1 + 代碼阻塞時間/代碼執行時間 ) * CPU數量
    • 因為我們無法精确時間
    • 實際情況是跑起代碼後,壓測環境進行調試。不斷調整線程數,将CPU達到80%到90%的使用率。
【Tomcat】Tomcat參數調優:連接配接數和并發數

打個比方:

有一家理發店(Tomcat),隻有兩個理發的位置(作業系統2核),假設一個洗剪吹(線程)接待(處理)一個客人(請求)需要30分鐘,休息(等待)30分鐘;請問這家理發店需要幾個洗剪吹才能高效輪班工作。答案肯定是4個。

4=(1+30/30)*2 ——————》(CPU處理至少一個線程+等待時間/處理時間)*2核

【Tomcat】Tomcat參數調優:連接配接數和并發數

假設CPU時間片是50ms,先排程一個線程來執行,執行完50ms的計算後,這個線程需要等待50ms,這時CPU就沒事幹了,但是他不能停下來,就會再排程一個線程來工作,那麼我們一個CPU隻需要兩個線程就可以把它打滿。(2個線程可以處理多個請求,現實中每個請求的處理時間不一緻,這就是我們程式代碼的品質展現)

4=(1+50/50)*2

6=(1+100/50)*2 (假如每個請求的等待時間很長,我們就可以安排多幾個線程來處理)

【Tomcat】Tomcat參數調優:連接配接數和并發數

實戰

【Tomcat】Tomcat參數調優:連接配接數和并發數
  • 1秒發送1000次,循環10次,也就是10秒發10*1000=1W個請求
    【Tomcat】Tomcat參數調優:連接配接數和并發數
    【Tomcat】Tomcat參數調優:連接配接數和并發數
    性能報告:
    【Tomcat】Tomcat參數調優:連接配接數和并發數
    這個linux是2核的,按照理論公式算出的4個線程的來測試的話:
    【Tomcat】Tomcat參數調優:連接配接數和并發數
    可以看到這個性能資料不是很滿意:響應時間要13秒,錯誤率30%
    【Tomcat】Tomcat參數調優:連接配接數和并發數
    将maxThread調回200,起碼沒有錯誤率,50個請求每秒吞吐量
    【Tomcat】Tomcat參數調優:連接配接數和并發數

    将maxThread調到300呢?

    這時開始有一些錯誤請求:因為現在的請求量全部堆積在服務端,這些請求如果20s沒有被處理就會請求逾時。

    是以調高了CPU處理不過來,調低了?CPU沒有打滿,有些請求沒有及時處理也會請求逾時。

    【Tomcat】Tomcat參數調優:連接配接數和并發數

    我們的代碼中50ms的等待時間,大概50ms的計算時間,一共響應時間大概是100ms,是以一個請求的程式響應時間本來就慢,吞吐量再怎麼調也高不到哪裡去,總結就是要提高我們自己的代碼品質。

    如果說CPU占用率太低的話,可以去調高我們的線程數。

先設定好容量200的線程池

【Tomcat】Tomcat參數調優:連接配接數和并發數

Spring結合servlet的異步處理

【Tomcat】Tomcat參數調優:連接配接數和并發數

有一些應用程式就是很慢,想通過多線程來加速是不可能的,用MQ和CaChe的确可以解決。

【Tomcat】Tomcat參數調優:連接配接數和并發數
【Tomcat】Tomcat參數調優:連接配接數和并發數

負載層+網關層+資料層

因為tomcat更大的作用是基礎元件,作用的是我們部署在上面的元件,Nginx是中間件,本身自帶很多功能。