多線程,到底該設置多少個線程?


一、前言

“不好了,線上服務器超時嚴重,請求非常慢,好像報連接數too many了,怎么辦?“小伙伴們在反饋。一般我們的技術老大的處理方式,把連接數和線程池調大點,重啟,再觀察。

往往這個方式是應急措施,治標不治本,因為不知道問題的原因。

有個嚴重誤區,以為線程池設置太小了,調大點請求就會快了。

今天就帶着小伙伴們溝通一下,線程池的大小應該如何合理的設置其大小?

二、問題

如果有兩個任務需要處理,一個任務A,一個任務B

方案一:一個線程執行任務A和B,A執行完后,執行B
方案二:兩個線程A和B去執行任務A 和 B,同時進行

哪個方案會快點?應該很多人會回答,肯定是方案二啊,多線程並行去處理任務A和B,肯定快啊。是這樣嗎?回答這個問題之前,先帶着大家去回顧梳理一下。

三、線程執行

線程的執行,是由CPU進行調度的,一個CPU在同一時刻只會執行一個線程,我們看上去的線程A 和 線程B並發執行。

為了讓用戶感覺這些任務正在同時進行,操作系統利用了時間片輪轉的方式,CPU給每個任務都服務一定的時間,然后把當前任務的狀態保存下來,在加載下一任務的狀態后,繼續服務下一任務。任務的狀態保存及再加載,這段過程就叫做上下文切換。

上下文切換過程是需要時間的;現在我們來看一下上面的問題,小伙伴們再看一下是哪個方案快呢?是不是有些小伙伴們會說方案一,因為不需要線程切換;方案二需要來回切換這兩個線程,耗時會多點。

小伙伴們心中此時是不是會有疑惑,那為什么會有多線程?先不急,再往下看。

四、為什么要多線程

小伙伴想想在我們真實業務中,我們是什么流程?

 

上圖的流程:

1、先發起網絡請求

2、Web服務器解析請求

3、請求后端的數據庫獲取數據

4、獲取數據后,進行處理

5、把處理結果放回給用戶

這個是我們處理業務的時候,常規的請求流程;我們看一下整個過程涉及到什么計算機處理。

1、網絡請求----->網絡IO

2、解析請求----->CPU

3、請求數據庫----->網絡IO

4、MySQL查詢數據----->磁盤IO

5、MySQL返回數據----->網絡IO

6、數據處理----->CPU

7、返回數據給用戶----->網絡IO

講到這里,小伙伴們是不是感覺又不亂了,在真實業務中我們不單單會涉及CPU計算,還有網絡IO和磁盤IO處理,這些處理是非常耗時的。如果一個線程整個流程是上圖的流程,真正涉及到CPU的只有2個節點,其他的節點都是IO處理,那么線程在做IO處理的時候,CPU就空閑出來了,CPU的利用率就不高。

小伙伴們現在知道多線程的用處了吧,對,就是為了提升CPU利用率。

五、提升QPS/TPS

衡量系統性能如何,主要指標系統的(QPS/TPS)

QPS/TPS:每秒能夠處理請求/事務的數量

並發數:系統同時處理的請求/事務的數量

響應時間:就是平均處理一個請求/事務需要時長

QPS/TPS = 並發數/響應時間

上面公式代表並發數越大,QPS就越大;所以很多人就會以為調大線程池,並發數就會大,也會提升QPS,所以才會出現一開始前言所說的,大多數人的誤區。

其實QPS還跟響應時間成反比,響應時間越大,QPS就會越小。

雖然並發數調大了,就會提升QPS,但線程數也會影響響應時間,因為上面我們也提到了上下文切換的問題,那怎么設置線程數的呢?

六、如何設置線程數

那我們如何分配線程?我們提供一個公式:

最佳線程數目 = ((線程等待時間+線程CPU時間)/線程CPU時間 )* CPU數目

備注這個公式也是前輩們分享的,當然之前看了淘寶前台系統優化實踐的文章,和上面的公式很類似,不過在CPU數目那邊,他們更細化了,上面的公式只是參考。不過不管什么公式,最終還是在生產環境中運行后,再優化調整。

我們繼續上面的任務,我們的服務器CPU核數為4核,一個任務線程cpu耗時為20ms,線程等待(網絡IO、磁盤IO)耗時80ms,那最佳線程數目:( 80 + 20 )/20 * 4 = 20。也就是設置20個線程數最佳。

從這個公式上面我們就得出,線程的等待時間越大,線程數就要設置越大,這個正好符合我們上面的分析,可提升CPU利用率。那從另一個角度上面說,線程數設置多大,是根據我們自身的業務的,需要自己去壓力測試,設置一個合理的數值。

七、基礎常規標准

那我們小伙伴們會問,因為很多業務集中到一個線程池中,不像上面的案例比較簡單,事實上業務太多,怎么設置呢?這個就是要去壓力測試去調整。不過我們的前輩已經幫我們總結了一個基礎的值(最終還是要看運行情況自行調整)

1、CPU密集型:操作內存處理的業務,一般線程數設置為:CPU核數 + 1 或者 CPU核數*2。核數為4的話,一般設置 5 或 8

2、IO密集型:文件操作,網絡操作,數據庫操作,一般線程設置為:cpu核數 / (1-0.9),核數為4的話,一般設置 40

八、總結

今天介紹了線程數大小的設置,一些小伙伴們的誤區。講到這里我們小伙伴們是不是對線程有了更新的理解,不像之前那么粗暴,應該要去分析為什么這么慢,系統的瓶頸出現在什么地方,減少瓶頸的耗時。

另外,推薦小伙伴們再去看一下Redis、Nginx;為什么他們會那么快呢?其實和這篇文章的知識點有共同的地方。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM