公司分配給我一個活,讓我給Kong網關作一個獲取設置的站點。Kong網關號稱幾萬的QPS的神器,我有點慌,若是由於個人站點拖累了Kong我就是千古罪人。服務器
配合Kong的站點必需要通過性能測試,在性能測試的時候就發現個頗有意思的現象,若是我用25條線程壓個人站點,那麼結果是這樣的。網絡
若是我用50條線程去壓站點,結果是這樣的多線程
現象就是,我提升了併發數量,個人QPS其實並無什麼變化,可是個人單次平均響應時間缺提升了一倍。其實這種現象仍是比較好解釋的。首先,咱們來了解一下,IIS的大概處理邏輯。併發
其實IIS維護了這麼幾個東西,首先一個是隊列,用來提升服務器的同時處理請求數用的。這麼說吧,假設我如今程序很原始很簡陋,我一次只能處理一條請求,那麼,我在處理一條請求的過程當中,第二條請求過來了,那麼這個時候我顯然不該該告訴他,我如今正忙,沒空搭理他,而應該是告訴他,你先等會,我立刻來處理你。讓他等會,其實就是至關於把他放到隊列裏邊,一會再來處理。性能
另一個概念叫作,同時處理數。剛纔個人假設是我一次只能處理一條數據。可是我存在多個核,就算是一核在一個時間點上只能處理一條數據,那麼,如今我機器是4核的,那麼我最起碼也應該能處理4條數據,假設如今一次性來了4條數據,那麼這4條數據基本上能夠認爲是同時在處理的,可是若是同時來了8條數據,那麼就是4條在處理,4條在等待。測試
如今來解釋一下,爲何會出現50併發比25併發,提高了等待時間,可是QPS並無提升。我想能夠這麼解釋,其實QPS在25併發的時候已經接近於極限了,這個極限應該怎麼算呢,大概就應該是1秒 * 同時處理數 / 每一個請求的真實處理時間。能夠看出來這個極限其實跟客戶端的併發數沒有什麼直接聯繫。那麼50併發的時候,爲何等待的時間反而變長了呢?那是由於,客戶端併發數大於服務器同時處理數的時候,有一部分固定數量的請求在請求隊列裏,他必須等待已經進入處理邏輯的部分處理完,而後再處理本身,因此就形成了QPS並無提高可是響應時間變長的現象發生。加密
由於是這樣的多倍疊加的模式,因此,有時候,你會發現,你的接口,若是隻是幾毫秒響應的話,你們都很快。可是一旦你慢下來,響應時間是成指數級的增加。緣由也很簡單,主要有如下幾個。線程
這幾個狀況一綜合那可不是乘法運算嘛,那可不就是指數級增長嘛。3d
提問,那麼究竟多少併發,纔是最理想的狀態呢?blog
以前考慮這個問題的時候,可能理所固然的認爲,這個東西嘛,應該是跟CPU核數有關係,應該跟核數同樣多就是最優解了吧。可是現實常常啪啪打臉。通過實測,通常是要比CPU核數多少很多才是CPU不累,處理效率很高的狀態。那麼爲何會出現這種狀況呢?我以爲這個問題有點大,咱們須要拆開來看。
一、一個核心真的是一條線程執行的最快嗎?
這個問題嘛,其實也對,也不對。說他對視由於,其實若是存在多條線程,那麼多條線程之間切換的時候,其實也挺消耗資源的。可是多線程的意義是什麼呢?我以爲這個問題也能夠拆成兩個問題。在拆問題以前先給介紹兩個概念。計算密集型、IO密集型,計算密集型就是你在作運算,加減乘除也好,比對也要,加密解密也好,這種主要依賴於CPU叫計算密集型線程。若是你的線程大部分時間都消耗在了讀取網絡數據,讀取本地數據,或者驅動硬件等待返回這種狀況叫作IO密集型。
1.1 一個核心真的是一個計算密集型最快嗎?
是的。由於線程自己也是須要消耗資源的,頻繁的切換其實對於計算密集型線程沒有任何好處,由於計算量並無變少反而變多了。
1.2 一個核心真的是一個IO密集型線程最快嗎?
不對。多個IO密集型線程確定比一個IO密集型線程要快,由於大部分時間,其實跟CPU沒有關係,CPU大部分時間都是在等而已。因此讓CPU一次性處理多個,反而更加佔有優點。
二、爲何不是併發量跟同時處理數相等時是最優解。
真實的業務場景,一條線程並非純粹的IO或者計算,更多的時候是處於二者都有的狀況。那麼對於這種線程的話。反正不是一核一個最快,由於它畢竟是存在IO的狀況。他們確定要多處理幾個才划算。
這樣服務器等待客戶端請求的時間就太長了,若是併發數量跟處理數量相等的話,那麼對於一個併發來講,就至關於客戶端發起請求、發送網絡數據、服務器處理、發送網絡數據、客戶端接收網絡數據,而後進行下一輪處理。這樣的話就至關於客戶端與服務器端處於同一個線程,單線程工做,而且中間存在了大量的等待的時間,因此服務器的QPS並不會上來。
最理想的狀態應該是,如下的狀態
根據上邊總結的多線程的相關結論,通常一個核心確定要處理多個線程,而且等待隊列中存在而且存在不了多少數據。
那麼最佳併發的結論應該是,核心數 * N(單核心同時處理線程數) + M(等待隊列中存在的少數請求)。
題外話:爲何Golang號稱利用協成可以更好的利用CPU 達到更高的運算效率呢?
我猜應該是將IO型線程中的多線程切換部分性能節省下來,用做於更多的CPU計算來提升了總體性能。