萬盛學電腦網

 萬盛學電腦網 >> 網頁制作 >> Html5 >> HTTP負載測試的方法

HTTP負載測試的方法

有很多人在談論HTTP負載測試,也許是因為現在有太多的服務器選擇。

這很好,但是我看到有人很多基本相同的問題,使得測試結果的推論值得懷疑。在日常工作中花費了很多時間在高性能代理緩存和源站性能測試方面之後,這裡有我認為比較重要的一些方面來分享。

希望能拋磚引玉。

0. 一致性

最最重要的是,每次都測試同一個時間點。因為系統發生的每個改變,無論是OS升級還是運行了其它消耗帶寬和CPU的應用,都會影響測試的結果,所以一定要把測試環境固定下來。

也許,有人會說那就把測試放虛擬機裡做吧,聽起來不錯。但是,這種方式加多了一個抽象層(而且宿主機上也跑了更多的進程),如果說這樣就能得到更加一致的結果,我是無論如何也不會相信的。我覺得,最好的辦法是為測試准備一套專用硬件。如果做不到這個,那麼一定要把所有測試放在同一個會話裡,不要去比較不同會話裡的測試結果。

1. 每台機器,各司其職

人們常常會犯另一個錯誤,他們把負載生成器和被測試的服務器放在同一台機器上。這樣做將導致產生不可靠的測試結果,因為,負載生成器實際上是「竊取」了一部分資源,而且這部分資源的量還會隨著服務器處理負載情況的變化而變化。

最好的做法是,為測試主體和負載生成器分配不同的硬件,而且將它們放在封閉的網絡上。這樣做的代價並不是太高,我們並不需要非常高精尖的配置,只需要確保一致性就好。

所以,如果有人跟你說,他們的測試是在localhost上做的,或者拒絕透露測試用了幾台機器,那麼你盡可以忽略他們的結果。因為,這樣的結果,往好了說,只有最基本的定性作用,往壞了說,甚至可能會誤人子弟。

2. 檢查網絡

在測試前,一定要知道你的網絡有多大容量,這樣,你才會知道,什麼時候是你測試的服務器制約了測試,什麼時候是網絡制約了測試。

一種方法是通過iperf:

qa1:~> iperf -c qa2

------------------------------------------------------------

Client connecting to qa2, TCP port 5001

TCP window size: 16.0 KByte (default)

------------------------------------------------------------

[  3] local 192.168.1.106 port 56014 connected with 192.168.1.107 port 5001

[ ID] Interval       Transfer     Bandwidth

[  3]  0.0-10.0 sec  1.10 GBytes   943 Mbits/sec

從上面的輸出中可以看到,我的千兆網可以達到943Mbps的速度(之所以不到1000Mbps,是由於TCP的開銷)。

知道網絡容量後,我們需要確保它不會成為制約測試的因素。有幾種方法,最簡單的是記錄當前使用的帶寬。例如,httperf可以像這樣展示當前的帶寬用量:

Net I/O: 23399.7 KB/s (191.7*10^6 bps)

上例表明,我們目前只用了192Mbps。

記住,我們在負載產生工具中看到的數字並沒有包括TCP開銷,而且,如果我們的負載在整個測試期間並不固定,那麼突發帶寬一定會有超過平均值的時候。而且除了帶寬以外還有其它的問題,例如,廉價的網卡和交換機很有可能會被大量的數據包淹沒。

HTTP負載測試

基於以上的種種原因,我們最好不要讓測試的帶寬逼近網絡的可用帶寬,最好是不要超過某個比例,比如2/3。對網絡(包括網卡和交換機)錯誤和峰值速率進行監控也是一個很好的辦法。

3. 去除OS限制

同樣,我們還需要確保OS不會對服務器的表現構成限制。

TCP參數的調整頗為重要,但它會對所有測試主體產生相同的影響。更為重要的是,不要讓你測試的服務器用光文件描述符(file descriptor)。

4. 避免壓測客戶端

現代高性能服務器使得容易將負載產生器的限制當作服務器的能力。所以,認真檢查以確保你的客戶端沒有用爆CPU,如果有任何懷疑,就使用更多客戶端壓力來驗證(autobench可以讓這件事更簡單)。

確保負載產生器的硬件優於要測試的服務端硬件,也很有幫助;比如,使用4核心的i5-750服務器產生負載,將服務器運行在較慢的雙核i3-350服務器上,而且經常只用兩個核心之一。

另外一個需要注意的因素是客戶端錯誤,尤其是臨時端口(ephemeral ports)用盡。處理這個問題有很多策略,擴大服務器的可用端口范圍,或設置多個網絡接口,確認由客戶端使用它們(有時需要一些技巧)。也可以優化TIME_WAIT時間(只有是測試環境就沒問題),或僅僅使用HTTP長連接和激進的客戶端超時策略,確保連接速率不會用盡端口數。

我喜歡httperf的一個原因是它在結束時提供了錯誤的概要:

Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0

Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0

這裡,服務器的問題位於第一行(比如由於服務器端超過--timeout設置的超時時間而造成的請求超時,或拒絕連接,或連接重置),客戶端錯誤(如文件描述符用盡或地址用盡)在第二行。

在測試本身出錯時,這能夠幫你及時了解。

5. 過載時的容量並不是真正的容量

產生盡可能大的負載,扔給服務器,這是許多負載產生工具的工作模式。

這種方法對於檢查服務器在過載情況下的表現也許不錯,但它並不能真正幫我們確定服務器的容量。因為,許多服務器在過載的情況下都會損失一部分的容量。

更好的方法是逐步加大負載,直到服務器達到容量上限,出現性能下降為止。我們可以把結果繪制成一條先抵達峰值、隨後下降的曲線,而下降的程度意味著服務器應對過載時的表現情況。

autobench是其中的一種方法,我們可以設置測試的范圍,然後就可以得到這樣一張圖:

HTTP負載測試

可以看到,在響應消息最小時,服務器的處理峰值為16,000響應/秒,但在過載情況下快速衰落至14,000響應/秒。而在響應消息更大時,過載情況下的衰落並沒有這麼多,但可以看到錯誤條不停彈出來,說明了服務器的緊張境況。

6. 30秒的測試不算測試

由於處於應用、OS與網絡棧各層的緩沖區需要一定的穩定時間,所以30秒的測試很可能不准確。如果你的測試數據是要正式發布的,請至少測試3分鐘,或者更長一些,比如5到10分鐘。

7. 不要僅僅測試Hello World

如果要測試服務器的響應是否迅速,用4字節的響應消息過於局限,意義不大,4k甚至100k才更有現實意義。

另外一個需要測試的是服務器在面對大量空閒連接時的表現,比如10,000個連接。這對現代的成熟服務器來說本來不算什麼,但往往會導致一些你想象不到的問題。

當然,以上僅僅只是兩個例子而已。

8. 僅僅平均值是不夠的

如果有人告訴你,服務器可以每秒產生1000個響應,平均時延為5ms,聽起來是不是很棒?但是,如果這1000個響應裡,有些需要100ms呢?或者,如果說在整個測試的10%時間裡,由於垃圾收集的關系,只能達到500個響應/秒的速度,你怎麼看?

平均值是個快速指標,但是,僅此而已。有許多重要的信息,包含在時間線和直方圖(histogram)中,但平均值並沒有提供。如果你的測試工具不提供時間線和直方圖,那麼還是換一個吧(開源的話,還可以選擇提交一個patch)。

httperf可以顯示:

Total: connections 180000 requests 180000 replies 180000 test-duration 179.901 s

Connection rate: 1000.0 conn/s (99.9 ms/conn, <=2 concurrent connections)

Connection time [ms]: min 0.4 avg 0.5 max 12.9 median 0.5 stddev 0.4

Connection time [ms]: connect 0.1

Connection length [replies/conn]: 1.000

Request rate: 1000.0 req/s (.9 ms/req)

Request size [B]: 79.0

Reply rate [replies/s]: min 999.1 avg 1000.0 max 1000.2 stddev 0.1 (35 samples)

Reply time [ms]: response 0.4 transfer 0.0

Reply size [B]: header 385.0 content 1176.0 footer 0.0 (total 1561.0)

Reply status: 1xx=0 2xx=0 3xx=0 4xx=1800 5xx=0

可以看到,它不僅顯示了響應速度的平均值,還顯示了最小值、最大值和標准差(deviation)。連接時間也是這樣。

9. 把相關信息全部發布出來

如果只是給出一個結果,而不給出重現它的必要信息,那麼往好了說,這個結果只是一個全憑大家靠信仰來相信的沒有用的結論,往壞了說,它甚至有故意誤人子弟之嫌(譯者注: 各種數據庫的宣傳式的benchmark表示紛紛中槍)。所以,如果要發布測試結果,記得要把測試的相關上下文也一起發布,不光是測試所用的硬件,還應包括OS版本與配置、網絡設置、服務器與負載產生器的版本與配置、所用的負載,甚至必要時還要加上源代碼。

理想情況下,我們可以采用代碼庫(比如github)的形式,使任何人都能以最小的代價(用自己的硬件)重現你的結果。

10. 嘗試不同工具

看到這裡,你也許會以為我只認httperf和autobench這兩個工具。我很喜歡全能型選手,可惜httperf不是。對於現代的一些服務器來說,httperf太慢了,也許是由於它缺乏事件循環的緣故。httper

copyright © 萬盛學電腦網 all rights reserved