如何決定 Web 應用的執行緒池大小

2021-07-10 09:28:12 字數 2352 閱讀 3177

在部署 web 應用到生產環境,或者在對 web 應用進行效能測試的時候,經常會有人問:如何決定 web 應用執行緒池大小?決定乙個 io 阻塞型 web 應用的執行緒池大小是一項很艱鉅的任務。通常是通過進行大量的效能測試來完成。在乙個 web 應用中同時擁有多個執行緒池會讓決定最優執行緒池大小的過程變得更加複雜。本文將就這個常見的問題進行一些討論和建議。

web 應用中的執行緒池大小決定了在指定時間內能夠處理的併發請求數。如果乙個 web 應用接收到的請求數高於執行緒池大小,多出來的請求將進入佇列等待,或被拒絕。

請注意併發和並行不是乙個概念。併發請求指的是正在處理中的請求數量,在某個時間點,只有其中的一小部分能夠得到 cpu 執行。而並行請求指的是正在處理的請求數量,在某個時間點,所有請求都在被 cpu 執行。

在非阻塞型 io 應用中,比如 nodejs,單個執行緒(程序)能夠同時處理多個請求。多核 cpu 處理器下,通過增加執行緒或程序數能夠處理並行請求。

在阻塞型 io 應用中,比如 springmvc,單個執行緒只能同時處理乙個請求。要同時處理多個併發請求的話,我們必須增加執行緒數量。

在計算密集型應用中,執行緒池的大小應該等同於主機中 cpu 的數量。再新增更多執行緒將會打斷請求的處理,因為執行緒的上下文切換也會延遲響應時間。

非阻塞型 io 應用將會是 cpu 密集型的,因為在請求得到處理的時候沒有執行緒等待時間。

決定 io 等待應用的執行緒池大小會由於依賴於下游系統的響應時間而變得更加複雜,因為乙個執行緒在其他系統響應之前始終是阻塞的。我們不得不像《

應答者模式:i/o 阻塞型應用》中討論的那樣去增加執行緒的數量以提高 cpu 利用率。

利特爾法則應用於非技術領域,比如銀行,以估算處理進入銀行客戶所需要的銀行出納櫃檯的數量。

利特爾法則在乙個穩定的系統中,長時間觀察到的平均顧客數量 l,等於長時間觀察到的有效到達速率,λ,與平均每個顧客在系統中花費的時間之乘積:l = λw

適用於 web 應用的利特爾法則乙個系統中線程的平均數量(threads),等於 web 請求的到達速率(webrequests per sec),與平均每個處理的響應時間(responsetime)的乘積

threads = 執行緒的數量

webrequests per sec = 一秒內能夠處理的 web 請求數

responsetime = 處理一次 web 請求所需要的時間

threads = (webrequests/sec) x responsetime

儘管上邊這個公式提供了處理進入請求的執行緒個數,它並沒有提供執行緒數和 cpu 核心數之間的比率資訊,比如乙個 x 個 cpu 的主機需要分配多少個執行緒。

要找出合適的執行緒池大小,需要在吞吐量和響應時間之間進行權衡。先以乙個最小值開始測試:乙個 cpu 乙個執行緒(也就是執行緒池大小 = cpu 個數),應用執行緒池大小與下游系統平均響應時間成正比增長,直到 cpu 使用率飽和或者響應時間開始退化為止。

下圖指出了請求數、cpu 以及響應時間等指標之間的關聯關係。

cpu vs 請求數演示了在增加 web 應用負載時的 cpu 利用率。

響應時間 vs 請求數圖演示了增加 web 應用負載對響應時間的影響。

綠點指出了最佳吞吐量和響應時間。

執行緒池大小 = cpu 個數

執行緒池很大

上圖描述的是 io 等待型應用在 web 應用中建立了很多執行緒的情況。由於有很多數量的執行緒,執行緒的上下文切換將會很頻繁。由於不必要的執行緒上下文切換,儘管吞吐量還沒公升上去的時候應用的 cpu 使用率就已經很高了。響應時間由於被請求的處理被執行緒的上下文切換所打斷而被拉長。

最佳執行緒池大小

上圖描述的是 io 等待型應用在 web 應用中建立了合理數量的執行緒的情況。cpu 得到了有效利用,具備良好的吞吐量和較少的執行緒上下文切換。我們可以看到由於更少的打斷(上下文切換),請求處理更加有效,應用有乙個良好的響應時間。

對於大多數 web 應用而言,只有少數幾種型別的 web 請求會花費比較長的處理時間。這些慢的請求處理可能會拖累所有執行緒,並降低整個應用的效能。

處理這種問題的兩個方案是:

決定乙個 io 阻塞型 web 應用的執行緒池大小是一項很艱鉅的任務。通常是通過進行大量的效能測試來完成。在乙個 web 應用中同時擁有多個執行緒池會讓決定最優執行緒池大小的過程變得更加複雜。

如何配置執行緒池大小

參考文件 一般需要根據任務的型別來配置執行緒池大小 如果是cpu密集型任務,就需要盡量壓榨cpu,參考值可以設為 ncpu 1 如果是io密集型任務,參考值可以設定為2 ncpu 當然,這只是乙個參考值,具體的設定還需要根據實際情況進行調整,比如可以先將執行緒池大小設定為參考值,再觀察任務運 況和系...

如何合理設定執行緒池大小

要想合理的配置執行緒池的大小,首先得分析任務的特性,可以從以下幾個角度分析 任務的性質 cpu密集型任務 io密集型任務 混合型任務。任務的優先順序 高 中 低。任務的依賴性 是否依賴其他系統資源,如資料庫連線等。性質不同的任務可以交給不同規模的執行緒池執行。對於不同性質的任務來說,cpu密集型任務...

如何合理設定執行緒池大小

這個問題雖然看起來很小,卻並不那麼容易回答。大家如果有更好的方法歡迎賜教,先來乙個天真的估算方法 假設要求乙個系統的tps transaction per second或者task per second 至少為20,然後假設每個transaction由乙個執行緒完成,繼續假設平均每個執行緒處理乙個t...