性能綜述的那三篇文章中,描述了各種指標,比如TPS、RPS、QPS、HPS、CPM等。我也強調了,我們在實際工作的時候,應該對這些概念有統一的認識。
這樣的話,在使用過程中,一個團隊或企業從上到下都具有同樣的概念意識,就可以避免出現溝通上的偏差。
我說一個故事。
我以前接觸過一個咨詢項目。在我接觸之前,性能測試團隊一直給老板匯報着一個數據,那就是10000TPS。並且在每個版本之后,都會出一個性能測試報告,老板一看,這個數據並沒有少於10000TPS,很好。 后來,我進去一看,他們一直提的這個10000TPS指的是單業務的訂單,並且是最基礎的訂單邏輯。那么問題來了,如果混合起來會怎么樣呢?於是我就讓他們做個混合容量場景,顯然,提容量不提混合,只說單接口的容量是不能滿足生產環境要求的。
結果怎么樣呢?只能測試到6000TPS。於是我就要去跟老板解釋說系統達到的指標是6000TPS。老板就惱火了呀,同樣的系統,以前報的一直是10000TPS,現在怎么只有6000TPS了?不行,你們開發的這個版本肯定是有問題的。於是老板找到了研發VP,研發VP找到了研發經理,研發經理找了研發組長,研發組長又找到了開發工程師,開發工程師找到了我。我說之前不是混合場景的結果,現在混合容量場景最多達到6000TPS,你們可以自己來測。
然后證明,TPS確實只能達到6000。然后就是一輪又一輪的向上解釋。
說這個故事是為了告訴你,你用TPS也好,RPS也好,QPS也好,甚至用西夏文來定義也不是不可以,只要在一個團隊中,大家都懂就可以了。
但是,在性能市場上,我們總要用具有普適性的指標說明,而不是用混亂的體系。
在這里,我建議用TPS做為關鍵的性能指標。那么在今天的內容里,我們就要說明白TPS到底是什么。在第3篇文章中,我提到過在不同的測試目標中設置不同的事務,也就是TPS中的T要根據實際的業務產生變化。
那么問題又來了,TPS和並發數是什么關系呢? 在並發中誰來承載”並發“這個概念呢?
說到這個,我們先說一下所謂的“絕對並發”和“相對並發”這兩個概念。絕對並發指的是同一時刻的並發數;相對並發指的是一個時間段內發生的事情。
你能詳細說一下這兩個概念之間的區別嗎?如果說不出來那簡直太正常了,因為這兩個概念把事情說得更復雜了。
什么是並發
下面我們就來說一下“並發”這個概念。
我們假設上圖中的這些小人是嚴格按照這個邏輯到達系統的,那顯然,系統的絕對並發用戶數是4。如果描述1秒內的並發用戶數,那就是16。是不是顯而易見?
但是,在實際的系統中,用戶通常是這樣分配的:
也就是說,這些用戶會分布在系統中不同的服務、網絡等對象中。這時候”絕對並發“這個概念就難描述了,你說的是哪部分的絕對並發呢?
要說積分服務,那是2;要說庫存服務,那是5;要說訂單服務,它自己是5個請求正在處理,但同時它又hold住了5個到庫存服務的鏈接,因為要等着它返回之后,再返回給前端。所以將絕對並發細分下去之后,你會發現頭都大了,不知道要描述什么了。
有人說,我們可以通過CPU啊,I/O啊,或者內存來描述絕對並發,來看CPU在同一時刻處理的任務數。如果是這樣的話,絕對並發還用算嗎?那肯定是CPU的個數呀。有人說CPU 1ns就可以處理好多個任務了,這里的1ns也是時間段呀。要說絕對的某個時刻,任務數肯定不會大於CPU物理個數。
所以“絕對並發”這個概念,不管是用來描述硬件細化的層面,還是用來描述業務邏輯的層面,都是沒什么意義的。
我們只要描述並發就好了,不用有“相對”和“絕對”的概念,這樣可以簡化溝通,也不會出錯。
那么如何來描述上面的並發用戶數呢?在這里我建議用TPS來承載“並發”這個概念。
並發數是16TPS,就是1秒內整個系統處理了16個事務。
這樣描述就夠了,別糾結。
在線用戶數、並發用戶數怎么計算
那么新問題又來了,在線用戶數和並發用戶數應該如何算呢?下面我們接着來看示意圖:
如上圖所示,總共有32個用戶進入了系統,但是綠色的用戶並沒有任何動作,那么顯然,在線用戶數是32個,並發用戶數是16個,這時的並發度就是50%。
但在一個系統中,通常都是下面這個樣子的。
為了能hold住更多的用戶,我們通常都會把一些數據放到Redis這樣的緩存服務器中。所以在線用戶數怎么算呢,如果僅從上面這種簡單的圖來看的話,其實就是緩存服務器能有多大,能hold住多少用戶需要的數據。
最多再加上在超時路上的用戶數。如下所示:
所以我們要是想知道在線的最大的用戶數是多少,對於一個設計邏輯清晰的系統來說,不用測試就可以知道,直接拿緩存的內存來算就可以了。
假設一個用戶進入系統之后,需要用10k內存來維護一個用戶的信息,那么10G的內存就能hold住1,048,576個用戶的數據,這就是最大在線用戶數了。在實際的項目中,我們還會將超時放在一起來考慮。
但並發用戶數不同,他們需要在系統中執行某個動作。我們要測試的重中之重,就是統計這些正在執行動作的並發用戶數。
當我們統計生產環境中的在線用戶數時,並發用戶數也是要同時統計的。這里會涉及到一個概念:並發度。
要想計算並發用戶和在線用戶數之間的關系,都需要有並發度。
做性能的人都知道,我們有時會接到一個需求,那就是一定要測試出來系統最大在線用戶數是多少。這個需求怎么做呢?
很多人都是通過加思考時間(有的壓力工具中叫等待時間,Sleep時間)來保持用戶與系統之間的session不斷,但實際上的並發度非常非常低。
我曾經看到一個小伙,在一台4C8G的筆記本上用LoadRunner跑了1萬個用戶,里面的error瘋狂上漲,當然正常的事務也有。我問他,你這個場景有什么意義,這么多錯?他說,老板要一個最大在線用戶數。我說你這些都錯了呀。他說,沒事,我要的是Running User能達到最大就行,給老板交差。我只能默默地離開了。
這里有一個比較嚴重的理解誤區,那就是壓力工具中的線程或用戶數到底是不是用來描述性能表現的?我們通過一個示意圖來說明:
通過這個圖,我們可以看到一個簡單的計算邏輯:
- 如果有10000個在線用戶數,同時並發度是1%,那顯然並發用戶數就是100。
- 如果每個線程的20TPS,顯然只需要5個線程就夠了(請注意,這里說的線程指的是壓力機的線程數)。
- 這時對Server來說,它處理的就是100TPS,平均響應時間是50ms。50ms就是根據1000ms/20TPS得來的(請注意,這里說的平均響應時間會在一個區間內浮動,但只要TPS不變,這個平均響應時間就不會變)。
- 如果我們有兩個Server線程來處理,那么一個線程就是50TPS,這個很直接吧。
- 請大家注意,這里我有一個轉換的細節,那就是並發用戶數到壓力機的並發線程數。這一步,我們通常怎么做呢?就是基准測試的第一步。關於這一點,我們在后續的場景中交待。
而我們通常說的“並發”這個詞,依賴TPS來承載的時候,指的都是Server端的處理能力,並不是壓力工具上的並發線程數。在上面的例子中,我們說的並發就是指服務器上100TPS的處理能力,而不是指5個壓力機的並發線程數。請你切記這一點,以免溝通障礙。
在我帶過的所有項目中,這都是一個溝通的前提。
所以,我一直在強調一點,這是一個基礎的知識:不要在意你用的是什么壓力工具,只要在意你服務端的處理能力就可以了。
示例
上面說了這么多,我們現在來看一個實例。這個例子很簡單,就是:
JMeter(1個線程) - Nginx - Tomcat - MySQL
通過上面的邏輯,我們先來看看JMeter的處理情況:
summary + 5922 in 00:00:30 = 197.4/s Avg: 4 Min: 0 Max: 26 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
summary = 35463 in 00:03:05 = 192.0/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
summary + 5922 in 00:00:30 = 197.5/s Avg: 4 Min: 0 Max: 24 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
summary = 41385 in 00:03:35 = 192.8/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
summary + 5808 in 00:00:30 = 193.6/s Avg: 5 Min: 0 Max: 25 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
summary = 47193 in 00:04:05 = 192.9/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
我們可以看到,JMeter的平均響應時間基本都在5ms,因為只有一個壓力機線程,所以它的TPS應該接近1000ms/5ms=200TPS。從測試結果上來看,也確實是接近的。有人說為什么會少一點?因為這里算的是平均數,並且這個數據是30s刷新一次,用30秒的時間內完成的事務數除以30s得到的,但是如果事務還沒有完成,就不會計算在內了;同時,如果在這段時間內有一兩個時間長的事務,也會拉低TPS。
那么對於服務端呢,我們來看看服務端線程的工作情況。
可以看到在服務端,我開了5個線程,但是服務端並沒有一直干活,只有一個在干活的,其他的都處於空閑狀態。
這是一種很合理的狀態。但是你需要注意的是,這種合理的狀態並不一定是對的性能狀態。
- 並發用戶數(TPS)是193.6TPS。如果並發度為5%,在線用戶數就是193.6/5%=3872。
- 響應時間是5ms。
- 壓力機並發線程數是1。這一條,我們通常也不對非專業人士描述,只要性能測試工程師自己知道就可以了。
下面我們換一下場景,在壓力機上啟動10個線程。結果如下:
summary + 11742 in 00:00:30 = 391.3/s Avg: 25 Min: 0 Max: 335 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
summary = 55761 in 00:02:24 = 386.6/s Avg: 25 Min: 0 Max: 346 Err: 0 (0.00%)
summary + 11924 in 00:00:30 = 397.5/s Avg: 25 Min: 0 Max: 80 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
summary = 67685 in 00:02:54 = 388.5/s Avg: 25 Min: 0 Max: 346 Err: 0 (0.00%)
summary + 11884 in 00:00:30 = 396.2/s Avg: 25 Min: 0 Max: 240 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
summary = 79569 in 00:03:24 = 389.6/s Avg: 25 Min: 0 Max: 346 Err: 0 (0.00%)
平均響應時間在25ms,我們來計算一處,(1000ms/25ms)*10=400TPS,而最新刷出來的一條是396.2,是不是非常合理?
再回來看看服務端的線程:
同樣是5個線程,現在就忙了很多。
- 並發用戶數(TPS)是396.2TPS。如果並發度為5%,在線用戶數就是396.2/5%=7924。
- 響應時間是25ms。
- 壓力機並發線程數是10。這一條,我們通常也不對非專業人士描述,只要性能測試工程師自己知道就可以了。
如果要有公式的話,這個計算公式將非常簡單:
$TPS = \frac{1000ms}{響應時間(單位ms)}*壓力機線程數$
我不打算再將此公式復雜化,所以就不再用字母替代了。
這就是我經常提到的,對於壓力工具來說,只要不報錯,我們就關心TPS和響應時間就可以了,因為TPS反應出來的是和服務器對應的處理能力,至少壓力線程數是多少,並不關鍵。我想這時會有人能想起來JMeter的BIO和AIO之爭吧。
你也許會說,這個我理解了,服務端有多少個線程,就可以支持多少個壓力機上的並發線程。但是這取決於TPS有多少,如果服務端處理的快,那壓力機的並發線程就可以更多一些。
這個邏輯看似很合理,但是通常服務端都是有業務邏輯的,既然有業務邏輯,顯然不會比壓力機快。
應該說,服務端需要更多的線程來處理壓力機線程發過來的請求。所以我們用幾台壓力機就可以壓幾十台服務端的性能了。
如果在一個微服務的系統中,因為每個服務都只做一件事情,拆分得很細,我們要注意整個系統的容量水位,而不是看某一個服務的能力,這就是拉平整個系統的容量。
我曾經看一個人做壓力的時候,壓力工具中要使用4000個線程,結果給服務端的Tomcat上也配置了4000個線程,結果Tomcat一啟動,稍微有點訪問,CS就特別高,結果導致請求沒處理多少,自己倒浪費了不少CPU。
總結
通過示意圖和示例,我描述了在線用戶數、並發用戶數、TPS(這里我們假設了一個用戶只對應一個事務)、響應時間之間的關系。有幾點需要強調:
- 通常所說的並發都是指服務端的並發,而不是指壓力機上的並發線程數,因為服務端的並發才是服務器的處理能力。
- 性能中常說的並發,是用TPS這樣的概念來承載具體數值的。
- 壓力工具中的線程數、響應時間和TPS之間是有對應關系的。
這里既沒有復雜的邏輯,也沒有復雜的公式。希望你在性能項目中,能簡化概念,注重實用性。