(點選上方公眾號,可快速關註)
來源:ImportNew – paddx
問題:
我寫了一個服務,併為每個請求分配一個執行緒來處理,我這樣做的原因是因為基本上每個請求都是一次資料庫的查詢操作。我使用了一個執行緒池的庫來減少執行緒的建立和銷毀。
我的問題是:像這樣的I/O多執行緒,什麼才是一個好的臨界點?我知道這需要一個粗略的估計值,但這個值應該是幾百呢還是幾千?
更新:
非常感謝你們所有的回答,看起來我需要去測試找出執行緒數上限,問題是:我怎麼知道執行緒數已經到達了上限?我究竟該如何去測量?
回答:
有的人可能會說,兩個執行緒就算是太多的執行緒了。我不是特別同意這種看法。
我的建議是:測試,而不是猜想。我建議把執行緒數設定為可配置的,並初始化為100個執行緒,然後執行你的軟體並對它進行監控。
如果執行緒的使用峰值才為3,那說明100個執行緒就是太多了。如果一天中的大部分時間都保持在100個執行緒,那就將執行緒的數量提高到200,然後再監視其執行情況。
你確實可以讓你的程式碼自動監控執行緒的使用,併在下次啟動的時候自動修改配置選項,但沒必要這麼做。
詳述:
我不支援經常變動你的執行緒池,而是盡可能的使用某一個值,你可能會問一個執行緒池合適的臨界點是什麼,現假定你的執行緒池可以限制執行緒池的最大執行緒數(這是一件非常好的事情)。
我寫過執行緒池和資料庫連線池,他們擁有以下最基本的特徵(我認為這些對系統的效能來說是必要的):
-
最小活動執行緒數
-
最大執行緒數
-
多久關閉一個未被使用的執行緒
第一條是為了確保執行緒池的最低效能標準(這些執行緒是一直可以被使用的)。第二條是為了限制活動執行緒的資源使用。第三條是在一定的時間內將執行緒數傳回到基準的設定,以減少資源的使用。
你需要去平衡執行緒未被完全使用(情況A)和沒有足夠的工作執行緒(情況B)的情況。
A通常指記憶體的使用(棧等等),因為一個不工作的執行緒不會佔用太多的CPU資源。B通常會延遲處理到達請求,直到有可以使用的執行緒。
這就是為什麼要去測算,正如你遇到的這種情況,絕大部分執行緒需要等待資料庫的響應才能執行。這就有兩個主要因素影響執行緒的數量:
第一個因素是資料庫的有效連線數。這是一個硬性的限制,除非你能透過資料庫管理系統增加資料庫的連線數。在這裡,我假設你的資料庫管理系統能夠承擔的資料庫連線數是無限制的。(雖然,理想情況下,你也應該測量一下)
其次,執行緒數量應該依賴於你係統的歷史執行情況。最小的執行緒數你應該設定為在歷史最低的執行緒數的基礎上加上A%和一個絕對的最小數值(例如,讓它也可被配置,就像A一樣)5。
執行緒池的最大數應該設定為在歷史最大執行緒數的基礎上加上B%。
你也應該監控你係統執行情況的變化,如果因為某些原因,在某一個非常重要的時刻,你的執行緒池使用率達到100%(這將影響你客戶端的效能),這就應該增加你執行緒池所允許的最大執行緒的數量,使其再增加B%。
對於“我究竟如何去測試”的回答:
你應該明確測算當前執行(例如,等待資料庫呼叫的傳回)負載下的最大執行緒數量。然後增加一個安全因子,如10%(強調一下,很多人貌似把我舉得例子當做了固定的建議)
此外,在生產環境下,這點也應該是需要去調節的。在剛開始的時候先估計一個值是沒問題的,但是,你永遠也無法預料生產環境下會產生什麼情況(這就是為什麼要把所有的這些都設定為執行時可配置的原因)。這就能應付各種客戶端呼叫時所出現的不可預期的情況。
看完本文有收穫?請轉發分享給更多人
關註「ImportNew」,提升Java技能