天天看點

淺談高并發

前言

但凡是網際網路的程式員,應該都夢想着自己的應用能夠被大量的使用者所使用。當大量使用者同時使用時,不可避免會出現高并發的問題。人人都在談高并發,那麼什麼是高并發呢?最近在工作裡,我發現我自己對高并發原來一直都是了解錯誤的。下面我将我自己了解的過程一步一步寫下來。

QPS

作為一個小白程式員,最開始了解的高并發就是伺服器在一瞬間内同時湧進大量的請求。一秒算一瞬間吧,那麼一秒内如果請求數很高應該算高并發吧?業界用QPS(Query Per Second)來描述一台查詢伺服器在一秒内能夠完成的查詢數,現在也用來表示每秒的請求數(Request Per Second)。剛入職的時候剛剛接觸到各個系統的調用保護政策都是限制了QPS,就認為QPS就代表着高并發,高并發就代表着高QPS。最近工作中嘗試壓測才發現這種想法真是太天真了。

先舉一個簡單的例子來反駁QPS就是高并發的想法。假設伺服器響應速度特别快,一個請求隻需要0.1ms就可以傳回,花費的記憶體和CPU也很低。假設隻有一個使用者在不停地串行請求伺服器,那麼1s内伺服器能處理10000個請求,QPS就是10000。這個QPS已經不低了,但是因為是串行,伺服器每個時間段隻接受一個請求,隻需要處理一個請求,是以負載非常低。這明顯不符合高并發下伺服器負載嚴重的特征。

再舉一個例子。當我嘗試使用JMeter進行壓測時,為了限制影響,把QPS的限制設定為20。實際壓測過程中監控QPS确實也在20左右波動,照理說如果用QPS作為高并發名額,現在的情況應該根本不算高并發。但是實際情況卻是機器負載瞬間飙升,所有的服務都幾乎癱瘓。最後查原因,發現我使用了400個并發線程去請求伺服器。

并發

上面已經闡釋了QPS并不等于高并發,那麼到底高并發是怎麼産生的呢?其實從高并發這個名字就可以看出,并發強調的是并行,也就是在同一時間會有很多并行的請求。

我先解釋一下上面第二個例子發生的原因,為什麼QPS隻有20,機器負載還是這麼大?伺服器在接受到一個請求時,如果是動态頁面,會調用CGI讓程式去生成這個界面。根據語言或架構的不同,有的會一個請求産生一個程序去處理,有的會一個請求産生一個線程去處理。這樣的一個程序或者一個線程就會對記憶體和CPU有固定的消耗(即使如Nodejs這樣使用單線程處理所有請求,處理每個請求本身還是會消耗記憶體和CPU)。

如果某一個瞬間并行的請求太多,就會嚴重消耗記憶體和CPU,造成伺服器負載過高。不管是CPU到達瓶頸還是記憶體達到瓶頸都會嚴重影響伺服器處理請求的速度,結果就是伺服器每秒能夠處理的請求數下降,QPS降低。

繼續閱讀