qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          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開銷,而且,如果我們的負載在整個測試期間并不固定,那么突發帶寬一定會有超過平均值的時候。而且除了帶寬以外還有其它的問題,例如,廉價的網卡和交換機很有可能會被大量的數據包淹沒。

            基于以上的種種原因,我們最好不要讓測試的帶寬逼近網絡的可用帶寬,最好是不要超過某個比例,比如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是其中的一種方法,我們可以設置測試的范圍,然后就可以得到這樣一張圖:

            可以看到,在響應消息最小時,服務器的處理峰值為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太慢了,也許是由于它缺乏事件循環的緣故。httperf只能以每秒50到500個請求的速度測試一些PHP應用,但無論如何也做不到以每秒上萬個請求的速度去測試那些現代的web服務器。

            而且,如果只認準一個工具的話,可能會由于客戶端與服務器之間一些奇怪的交互,導致對某個實現特別不利的情況發生。例如,有些工具建立持久連接的方式對一些服務器不夠友好,導致它們的測試結果不佳。

            而我之所以喜歡httperf,上文中也已經提過,由于它有很詳細的統計信息和錯誤報告,而且可以自定義負載速率,讓我們可以更清晰地了解我們的服務器。我希望其它工具也能輸出同樣詳細的信息。

            我最近還用了siege,雖然在信息方面還比不上httperf那么詳細,不過也很好用,尤其速度真叫一個快。

            原文鏈接:http://www.oschina.net/translate/http_benchmark_rules

          posted on 2013-05-03 10:34 順其自然EVO 閱讀(265) 評論(0)  編輯  收藏 所屬分類: web 前端性能測試

          <2013年5月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 乐安县| 海安县| 云安县| 宜都市| 年辖:市辖区| 朔州市| 台山市| 彭泽县| 华亭县| 图木舒克市| 抚松县| 金堂县| 疏附县| 东光县| 临安市| 南昌市| 南部县| 若尔盖县| 博客| 汾阳市| 顺平县| 登封市| 奉节县| 新乡县| 新巴尔虎右旗| 盐边县| 丰顺县| 仙游县| 博客| 开远市| 屏南县| 宽城| 枣庄市| 盖州市| 高要市| 灵武市| 利津县| 阆中市| 庄浪县| 黄骅市| 兰西县|