【LocustPlus序】漫談服務端效能測試

debugtalk發表於2016-11-02

最近因為工作原因,我又拾起了老本行,開始做Web效能測試。之前雖然做過三四年的效能測試,但是在部落格和開源專案方面都沒有什麼輸出,一直是一個很大的遺憾。因此,近期打算圍繞服務端效能測試的話題,將自己在這方面的經歷進行整理。並且,最近使用的效能測試工具Locust感覺挺不錯的,只是其功能比較單薄,特別是在效能指標監控和測試報告圖表方面比較缺失,因此也打算在Locust的基礎上做二次開發,打造一款自己用得順手的效能測試工具,暫且將其命名為LocustPlus吧。

簡述效能測試

提起效能測試,可能移動APP的從業人員會感覺比較混淆,因為在客戶端(Android、iOS)中也有效能測試專項,主要涉及的是APP的啟動時間、記憶體、包大小、幀率,流量等客戶端相關的指標。在本部落格之前的文章中,也包含了一些客戶端效能測試的內容。需要說明的是,本文所講解的效能測試都是針對伺服器端,尤指Web系統的,與移動APP的效能測試完全是不同的領域。

那麼,什麼是服務端的效能測試呢?

先從大家都熟悉的功能測試說起吧。例如,我們要測試一個搜尋功能,那麼我們測試時,就會輸入搜尋關鍵詞,點選搜尋按鈕,然後再去檢視搜尋結果,看結果是否跟我們輸入的搜尋關鍵詞匹配,如果匹配則說明搜尋功能實現正確。

【LocustPlus序】漫談服務端效能測試
Google Search

那如何對該功能進行效能測試呢?

答案就是,N個人同時進行功能性操作的同時,在確保功能實現正確的前提下,考察服務端應用程式的各項效能指標,以及伺服器硬體資源的使用情況。

當然,這個答案比較簡單粗暴,但是它仍然包含了效能測試的基本特點:

  • 以功能實現正確為前提
  • 通常有一定的併發使用者
  • 重點考察伺服器端在一定併發壓力下的效能指標

最後,再明確下效能測試的目的。通常,對伺服器端應用程式開展效能測試,是為了驗證軟體系統是否能夠達到預期的效能指標,同時發現軟體系統中存在的效能瓶頸,從而實現優化系統的目的。

效能測試方法的核心

根據不同的測試目的,效能測試可以分為多種型別,常見的有如下幾類:

  • 基準測試(Standard Testing)
  • 負載測試(Load Testing)
  • 壓力測試(Stress Testing)
  • 疲勞強度測試

首先說下基準測試。基準測試指的是模擬單個使用者執行業務場景時,考察系統的效能指標。嚴格意義上來講,基準測試並不能算作效能測試範疇,它跟功能測試並沒有太大區別。差異在於,基準測試的目的更多地是關注業務功能的正確性,或者說驗證測試指令碼的正確性,然後,將基準測試時採集得到的系統效能指標,作為基準測試結果,為後續併發壓力測試的效能分析提供參考依據。

負載測試,主要指的是模擬系統在正常負載壓力場景下,考察系統的效能指標。這裡說的正常負載,主要是指使用者對系統能承受的最大業務負載量的期望值,即預計系統最大應該支援多大使用者的併發量。通過負載測試,目的是驗證系統是否能滿足預期的業務壓力場景。

和負載測試的概念比較接近的是壓力測試。通俗地講,壓力測試是為了發現在多大併發壓力下系統的效能會變得不可接受,或者出現效能拐點(崩潰)的情況。在加壓策略上,壓力測試會對被測系統逐步加壓,在加壓的過程中考察系統效能指標的走勢情況,最終找出系統在出現效能拐點時的併發使用者數,也就是系統支援的最大併發使用者數。

最後再說下疲勞強度測試。其實疲勞強度測試的加壓策略跟負載測試也很接近,都是對系統模擬出系統能承受的最大業務負載量,差異在於,疲勞強度測試更關注系統在長時間執行情況下系統效能指標的變化情況,例如,系統在執行一段時間後,是否會出現事務處理失敗、響應時間增長、業務吞吐量降低、CPU/記憶體資源增長等問題。

通過對比可以發現,不同的效能測試型別,其本質的差異還是在加壓策略上,而採用何種加壓策略,就取決於我們實際的測試目的,即期望通過效能測試發現什麼問題。明白了這一點,效能測試型別的差異也就不再容易混淆了。

結論要點1:效能測試手段的重點在於加壓的方式和策略。

效能瓶頸定位的核心

在前面頻繁地提到了效能指標,那效能指標究竟有哪些,我們在效能測試的過程中需要重點關注哪些指標項呢?

從維度上劃分,效能指標主要分為兩大類,分別是業務效能指標和系統資源效能指標。

業務效能指標可以直觀地反映被測系統的實際效能狀況,常用的指標項有:

  • 併發使用者數
  • 事務吞吐率(TPS/RPS)
  • 事務平均響應時間
  • 事務成功率

而系統資源效能指標,主要是反映整個系統環境的硬體資源使用情況,常用的指標包括:

  • 伺服器:CPU利用率、處理器佇列長度、記憶體利用率、記憶體交換頁面數、磁碟IO狀態、網路卡頻寬使用情況等;
  • 資料庫:資料庫連線數、資料庫讀寫響應時長、資料庫讀寫吞吐量等;
  • 網路:網路吞吐量、網路頻寬、網路緩衝池大小;
  • 快取(Redis):靜態資源快取命中率、動態資料快取命中率、快取吞吐量等;
  • 測試裝置(壓力發生器):CPU利用率、處理器佇列長度、記憶體利用率、記憶體交換頁面數、磁碟IO狀態、網路卡頻寬使用情況等。

對於以上指標的具體含義我就不在此進行逐一說明了,大家可以自行搜尋,務必需要搞清楚每個指標的概念及其意義。可能有些指標在不同的作業系統中的名稱有些差異,但是基本都會有對應的指標,其代表的意義也是相通的。例如,處理器佇列長度這個指標,在Windows中的指標名稱是System\Processor Queue Length,而在Linux系統中則需要看load averages

可能對於最後一項(測試裝置)有些人不大理解,監控被測系統環境的相關硬體資源使用情況不就好了麼,為什麼還要關注測試裝置本身呢?這是因為測試裝置在模擬高併發請求的過程中,裝置本身也會存在較高的資源消耗,例如CPU、記憶體、網路卡頻寬吃滿,磁碟IO讀寫頻繁,處理器排隊嚴重等;當出現這類情況後,測試裝置本身就會出現瓶頸,無法產生預期的併發壓力,從而我們測試得到的資料也就不具有可參考性了。此處暫不進行展開,後面我會再結合實際案例,通過圖表和資料對此詳細進行說明。

需要說明的是,效能指標之間通常都是有密切關聯的,單純地看某個指標往往很難定位出效能瓶頸,這需要我們對各項效能指標的含義瞭然於胸,然後才能在實際測試的過程中對系統效能狀況綜合進行分析,找出整個系統真正的瓶頸。舉個簡單的例子,壓力測試時發現伺服器端CPU利用率非常高,那這個能說明什麼問題呢?是服務端應用程式的演算法問題,還是伺服器硬體資源配置跟不上呢?光看這一個指標並不能定位出產生問題的真正原因,而如果僅因為這一點,就決定直接去優化程式演算法或者升級伺服器配置,最後也很難真正地解決問題。

結論要點2:效能瓶頸定位的重點在於效能指標的監控和分析。

引入效能測試工具

通過前面的講解,我們已經知道效能測試的主要手段是通過產生模擬真實業務的壓力對被測系統進行加壓,與此同時監控被測系統的各項效能指標,研究被測系統在不同壓力情況下的表現,找出其潛在的效能瓶頸。

那麼,如何對系統進行加壓,又如何對系統的指標進行監控呢?這裡,就需要引入效能測試工具了。

當然,我們也可以先看下在不借助效能測試工具的情況下,如何手工地對系統進行效能測試。

假設現在我們要對前面提到的搜尋功能進行負載測試,驗證在20個併發使用者下搜尋功能的事務平均響應時間是否在3秒以內。

很自然地,我們可以想到測試的必要條件有如下幾點:

  • 20個測試人員,產生業務壓力
  • 1個指揮人員,對20個人員的協調控制,實現併發操作
  • 1個結果記錄人員,對每一個人員的操作耗時進行監控和記錄
  • 若干資源監控人員,實時檢視被測系統的各項效能指標,對指標進行彙總、分析
  • 1個結果統計人員,對20個使用者各操作消耗的時長進行彙總,計算其平均值

可以看出,要通過人工來進行效能測試,操作上極為繁瑣,需要投入的資源非常多,而這還僅僅是一個非常簡單的場景。設想,如果要測試10000併發,伺服器有好幾十臺,顯然,這種情況下是完全不可能通過投入人力就能解決的。這也就是效能測試工具存在的必要性和誕生的背景。

效能測試工具的基本組成

當前,市面上已經有了很多效能測試工具,但不管是哪一款,基本都會包含如下幾個核心的模組。

  • 壓力生成器(Virtual User Generator)
  • 結果採集器(Result Collector)
  • 負載控制器(Controller)
  • 系統資源監控器(Monitor)
  • 結果分析器(Analysis)

原理結構圖如下所示:

【LocustPlus序】漫談服務端效能測試
Google Search

對照前面手工進行效能測試的案例,不難理解,壓力發生器對應的是眾多測試人員,結果採集器對應的是結果記錄人員,負載控制器對應的是指揮人員,資源監控器對應的是若干資源監控人員,結果分析器對應的是結果統計人員。

其中,壓力發生器又是效能測試工具最核心的部分,它主要有兩個功能,一是真實模擬使用者操作,二是模擬有效併發。

然而,大多數效能測試工作人員可能都會忽略的是,當前市面上效能測試工具的壓力發生器基本都是存在缺陷的。

先說下模擬真實使用者操作。如果熟悉瀏覽器的工作原理,就會知道瀏覽器在載入網頁的時候,是同時併發多個TCP連線去請求頁面對應的HTTP資源,包括HTML、JS、圖片、CSS,當前流行的瀏覽器普遍會併發6-10個連線。然而,效能測試工具在模擬單個使用者操作的時候,基本上都是單連線序列載入頁面資源。產生的差異在於,假如頁面有100個資源,每個HTTP請求的響應時間約為100毫秒,那麼瀏覽器採用6個連線並行載入網頁時大概會需要1.7秒(100/6*100毫秒),而測試工具採用單連線序列載入就需要10秒(100*100毫秒),兩者結果相差十分巨大。這也解釋了為什麼有時候我們通過效能測試工具測試得到的響應時間挺長,但是手動用瀏覽器載入網頁時感覺挺快的原因。

再說下有效併發。什麼叫有效併發?有效併發就是我們在測試工具中設定了1000虛擬使用者數,實際在伺服器端就能產生1000併發壓力。然而現實情況是,很多時候由於測試裝置自身出現了效能瓶頸,壓力發生器產生的併發壓力遠小於設定值,並且通常測試工具也不會將該問題暴露給測試人員;如果測試人員忽略了這個問題,以為測試得到的結果就是在設定併發壓力下的結果,那麼最終分析得出的結論也就跟實際情況大相徑庭了。不過,我們可以通過保障測試環境不存在瓶頸,使得實際生成的併發壓力盡可能地與設定值一致;另一方面,我們也可以通過在測試過程中監控Web層(例如Nginx)的連線數和請求數,檢視實際達到伺服器端的併發數是否跟我們的設定值一致,以此來反推壓力發生器的壓力是否有效。

瞭解這些缺陷的意義在於,我們可以更清楚測試工具的原理,從而更準確地理解測試結果的真實含義。

效能測試工具推薦

經過充分的理論鋪墊,現在總算可以進入正題,開始講解工具部分了。

在效能測試工具方面,我重點向大家推薦Locust這款開源工具。目前階段,該款工具在國內的知名度還很低,大多數測試人員可能之前都沒有接觸過。為了便於理解,我先將Locust與LoadRunner、Jmeter這類大眾耳熟能詳的效能測試工具進行簡單對比。

\ LoadRunner Jmeter Locust
授權方式 商業收費 開源免費 開源免費
開發語言 C/Java Java Python
測試指令碼形式 C/Java GUI Python
併發機制 程式/執行緒 執行緒 協程
單機併發能力
分散式壓力 支援 支援 支援
資源監控 支援 不支援 不支援
報告與分析 完善 簡單圖表 簡單圖表
支援二次開發 不支援 支援 支援

通過對比,大家可能會疑惑,Locust也不怎麼樣嘛,資源監控也不支援,報告分析能力也這麼弱,那為啥還要選擇它呢?

授權方式這個就不說了。雖然LoadRunner是商業軟體,價格極其昂貴,但是國內盜版橫行,別說個人,就算是大型網際網路公司,用正版的也沒幾個。

從功能特性的角度來講,LoadRunner是最全面的,使用者群體也是最多的,相應的學習資料也最為豐富。個人建議如果是新接觸效能測試,可以先熟悉LoadRunner,藉此瞭解效能測試工具各個模組的概念和功能,在此基礎上再轉到別的測試工具,也都比較好上手了。不過,LoadRunner只能在Windows平臺使用,並且併發效率比較低,單臺壓力機難以產生較高的併發能力,這也是現在我棄用該款工具的主要原因。

同樣地,Jmeter的併發機制也是基於執行緒,併發效率存在同樣的問題;另外,Jmeter在指令碼編寫和描述方面是基於GUI操作,個人感覺操作比較繁瑣(這個因人而異),因此不是很喜歡。

那麼,我重點推薦的Locust有啥特別的地方呢?

如果從整體功能上來看的話,Locust的功能的確比較單薄。不過,作為效能測試工具最核心的壓力發生器部分,卻是非常不錯的。拋開官方文件的介紹,個人覺得最讚的有兩點。

首先是模擬使用者操作,也就是測試指令碼描述方面。Locust採用Pure Python指令碼描述,並且HTTP請求完全基於Requests庫。用過Requests的都知道,這個庫非常簡潔易用,但功能十分強大,很多其它程式語言的HTTP庫都借鑑了它的思想和模式,如果將其評選為最好用的HTTP庫之一(不限語言),應該也不會有太大的爭議。除了HTTP(S)協議,Locust也可以測試其它任意協議的系統,只需要採用Python呼叫對應的庫進行請求描述即可。

另外一點就是併發機制了。Locust的併發機制摒棄了程式和執行緒,採用協程(gevent)的機制。採用多執行緒來模擬多使用者時,執行緒數會隨著併發數的增加而增加,而執行緒之間的切換是需要佔用資源的,IO的阻塞和執行緒的sleep會不可避免的導致併發效率下降;正因如此,LoadRunner和Jmeter這類採用程式和執行緒的測試工具,都很難在單機上模擬出較高的併發壓力。而協程和執行緒的區別在於,協程避免了系統級資源排程,由此大幅提高了效能。正常情況下,單臺普通配置的測試機可以生產數千併發壓力,這是LoadRunner和Jmeter都無法實現的。

有了一個不錯的引擎,外表裝飾簡陋點也都是可以接受的了。不過雖然Locust功能單薄,特別是在效能指標監控和測試報告圖表方面比較缺失,但是Locust的程式碼結構清晰,核心程式碼量也只有幾百行,可擴充套件性也非常不錯。換言之,Locust的可玩性(hackable)極強,對於一個想深入挖掘效能測試工具原理的人來說,Locust非常適合。

好了,Locust的介紹暫且到這兒,後續我會再對Locust的使用方法和二次開發進行詳細介紹,也算是彌補官方文件的不足吧。

閱讀更多

debugtalk.com/post/locust…

相關文章