負載測試的端到端指南
譯文【51CTO.com快譯】眾所周知,功能性測試通常著眼于單個用戶對于目標應(yīng)用程序的基本使用體驗。而對成百上千的用戶同時訪問目標站點的場景,特別是那些面向公眾服務(wù)的Web應(yīng)用,開發(fā)人員勢必需要在應(yīng)用上線之前,模擬真實的并發(fā)訪問情況,并通過考慮和進行負載測試,為任何可能發(fā)生的問題與意外,做好充分的準備。
在本指南中,我將通過如下四個階段,向您介紹負載測試過程中的相關(guān)知識。
- 計劃:為何要測試?測試什么?
- 編寫測試腳本:如何測試?
- 執(zhí)行:針對應(yīng)用程序運行測試腳本。
- 分析和報告:發(fā)現(xiàn)了什么?需要修復(fù)什么?
計劃負載測試
在計劃階段,團隊會聚到一起,討論并確定包括目標、范圍、所需資源、以及測試場景等方面的內(nèi)容。此階段的可交付成果為測試計劃。不過,它在形式上是否正式,則取決于團隊的實際要求。值得注意的是,任何測試計劃都是一項團隊活動,我們需要從所有利益相關(guān)者(即:參與測試或可能受測試影響的任何人)處獲取建議。
要求
我們需要搞清楚為什么要做負載測試?該問題看似簡單,但是不同的利益相關(guān)者可能會給出不同的測試場景需求。因此為了達成一致,我們最好將負載測試的目標表述為非功能性的需求 (nonfunctional requirements,NFR),以便定義應(yīng)用程序的期望狀態(tài),并且能夠包括由團隊決定的性能閾值。例如:基于響應(yīng)時間的要求,已注冊的用戶登錄用時不應(yīng)超過3秒(即達到90%的響應(yīng)時間)??梢姡玫男枨笸軌驖M足:SMART(具體的Specific、可衡量的Measurable、已商定的Agreed Upon、可實現(xiàn)的Realistic、以及及時的Timely)等特點。而且在實踐中,我們可以從如下方面進行把控。
范圍
約定了負載測試的共同目標,我們不但可以縮小待測內(nèi)容的領(lǐng)域,還能確保每個成員都清楚有哪些部分不需要被測試。
先決條件
在開展測試之前,我們需要考慮包括:參與的人數(shù)、執(zhí)行測試所需的時間、以及測試數(shù)據(jù)的環(huán)境要求等多方面的資源與先決條件。雖然我們并不總是需要一個單獨的測試環(huán)境,來進行負載測試,但是如果需要的話,應(yīng)該事先知會DevOps等團隊。
負載建模
負載模型可以被用來描述模擬負載的一組特征。例如:用戶最常訪問的是哪些頁面、哪個服務(wù)部分、最長訪問的時段與地理位置等方面。您可以將這些因素植入測試腳本中,以更加真實地模擬出,可能對應(yīng)用程序產(chǎn)生的流量和影響。
服務(wù)器監(jiān)控
在測試過程中,我們往往需要通過腳本,來監(jiān)控后臺服務(wù)器上各類警報與日志。如果您的負載測試工具檢測到明顯的性能下降,則需要能夠通過關(guān)聯(lián)服務(wù)器上的相應(yīng)信息,來予以勘察。不過,值得注意的是,任何類型的監(jiān)控都會增加現(xiàn)有服務(wù)資源的開銷,因此整個團隊應(yīng)事先確定好需要監(jiān)控和跟蹤的指標與信息。
測試場景
待測試和模擬的場景設(shè)定,往往能夠協(xié)助我們更加準確地獲取網(wǎng)站與應(yīng)用的真實性能。例如:我們既可以創(chuàng)建一個典型工作日的負載配置文件,又可以模擬大促時的峰值負載配置文件,還可以模擬某個生產(chǎn)出現(xiàn)中斷時的場景。不同的測試場景能夠為我們采集到的諸如:持續(xù)時間、并發(fā)用戶數(shù)、請求數(shù)、激增周期(即:應(yīng)用從0個用戶上升到最大用戶量的速度)、以及“峰谷”負載(即:在整個測試過程中,每秒請求數(shù)的波動)等,可供分析的參數(shù)數(shù)據(jù)。
在設(shè)計負載測試計劃時,您既可以包含多條用戶故事線,又可以使用各種Trello卡片(譯者注:一種卡片式任務(wù)管理工具)。工具的輸出格式并不重要;重要的是每個成員都能夠從中解讀出一致性、規(guī)范化的測試結(jié)果。
編寫測試腳本
有了在前面計劃階段的各項準備,現(xiàn)在我們便可以開始通過編寫負載測試腳本,來為測試的實施做好準備了。
工具的選擇
目前,市場上有著許多負載測試類工具。出于對各種在用工具、以及財務(wù)和供應(yīng)商等方面的考量,我們不一定可以自由地按需選擇負載測試工具,但是如下方面還是值得我們認真考慮的:
資源和成本
- 整體購置的價格,及其定價模型是否允許用戶按需增減使用量?
- 實際需要自行構(gòu)建,還是應(yīng)當(dāng)購買端到端的負載測試方案?
- 團隊擁有哪些技術(shù)技能與工具經(jīng)驗?誰將負責(zé)進行測試?
特點
- 負載測試工具是否能夠支持應(yīng)用程序所使用的協(xié)議和技術(shù)?
- 測試工具與對應(yīng)腳本語言的學(xué)習(xí)曲線是否“陡峭”?
- 測試工具是否可以讓多人輕松地協(xié)作,并處理同一個腳本?
- 能否與測試棧中的其他可用于測試管理、測試結(jié)果分析、服務(wù)器監(jiān)控、團隊溝通等工具相集成?
- 測試工具能否被添加到CI/CD管道中?
- 該工具是否通過提供簡單的方法,來設(shè)置性能閾值或服務(wù)等級目標(SLO)?
- 測試結(jié)果能否顯示在可用的報告中,以及能否與現(xiàn)有的數(shù)據(jù)可視化工具相集成?
支持
- 如果出現(xiàn)問題,客戶支持是否需要通過額外付費才能獲取?
- 在線幫助文檔是否夠用?
- 是否擁有經(jīng)驗分享的用戶社區(qū)?
擴展負載測試
- 單個負載生成器每秒可模擬多少個虛擬用戶或請求?
- 能否處理由測試所產(chǎn)生的大數(shù)據(jù)量?
- 能否根據(jù)用戶的位置特征,從不同的地理位置實施測試?
- 是否允許用戶從云端生成負載?
鑒于上述需求,我選定k6(https://k6.io/)作為開發(fā)負載測試腳本的工具??偟恼f來,k6有著如下三方面的優(yōu)勢:
- 由于它是開源的,因此任何人都可以下載該工具,并親自試用其腳本。
- 由于是用JavaScript編寫而成,因此那些使用過Cypress、Puppeteer或Playwright等工具的前端開發(fā)人員、或測試人員都能夠輕松地上手。
- 由于它能夠在一臺機器上生成上萬個用戶的并發(fā)數(shù),因此即便在負載增加的情況下,它也具有一定的成本效益。
當(dāng)然,下面將要討論到的各個步驟也適用于其他工具。而且,我強烈建議您使用多種工具,自行進行概念驗證,以找到最適合特定情況和測試場景的工具。
安裝和設(shè)置
如果您使用的是Mac系統(tǒng),那么便可以使用Brew來輕松地安裝k6,即:從終端處運行--brew install k6,就能夠在幾秒鐘之內(nèi)搞定。當(dāng)然,如果您使用的是其他操作系統(tǒng)的話,請通過鏈接--https://k6.io/docs/getting-started/installation/,來獲取詳細的安裝說明。
一個基本的k6測試腳本
如下JavaScript代碼段展示了最基本的k6測試腳本:
- import http from ‘k6/http’;
- export default function () {
- let response = http.get(‘https://test.k6.io’);
- }
該腳本會向一個簡單的測試站點(其URL為https://test.k6.io)發(fā)送一個HTTP的GET請求。請將該代碼復(fù)制到文本編輯器中,并存為test.js文件。接著,您便可以使用命令--k6run test.js,來運行它,并得到如下顯示結(jié)果:
在k6中運行簡單的本地測試示例
從上述截圖中,我們可以看出,本地主器上的1個虛擬用戶執(zhí)行了1次腳本的迭代。而該HTTP測試請求的響應(yīng)時間為128.2毫秒(即:http_req_duration)。
使測試腳本更加真實
顯然,上述腳本的GET請求過于簡單,無法達到用負載測試腳本在數(shù)量、以及地理分布上模擬真實用戶的訪問情況。而如果負載測試腳本不夠真實,則會在測試期間產(chǎn)生誤報,甚至無法讓用戶發(fā)現(xiàn)應(yīng)用組件潛在的性能問題。下面,我們來討論一下如何讓測試腳本更為真實。
添加靜態(tài)資源
如果頁面上帶有可被瀏覽器自動檢索到的圖像或腳本等靜態(tài)資源,那么請確保測試腳本也會去檢索此類資源。畢竟它們會影響到您獲得頁面的響應(yīng)時間。當(dāng)然,如果您已經(jīng)獲得了來自第三方提供商的許可,那么您也可以考慮從第三方處獲取靜態(tài)資源。
設(shè)置緩存和cookie行為
雖然站點的首次訪問者無法調(diào)用本地的緩存資源,但是重復(fù)訪問者則會從緩存中檢索相應(yīng)的資源。對此,我們應(yīng)當(dāng)檢查負載測試工具的默認緩存和cookie管理的設(shè)置,并通過按需更改,來匹配真實的測試場景。
添加“思考時間”
真正的用戶通常不會不停地反復(fù)刷新相同的URL。他們在導(dǎo)航到目標網(wǎng)站后,會花一些時間閱讀頁面上的內(nèi)容,與頁面上的某些組件進行交互。這些用戶的“思考”時間其實就是各個請求之間的延遲。因此,通過添加1到5秒的“思考時間”,我們可以讓應(yīng)用服務(wù)器免于遭受外掛機器人發(fā)出的請求轟炸。
使用不同的用戶路徑
用戶路徑是指用戶如何與應(yīng)用程序進行交互的流程,其中包括:他們會訪問哪些頁面,輸入哪些信息等。我們前面在計劃階段所建立的工作負載模型,可以直接反映出系統(tǒng)中最常見的用戶流程,例如:使用不同的瀏覽器進行登錄,或是從購物車中選擇商品付款等。在k6中,我們可以通過添加不同的場景來實現(xiàn),而其他工具則可能稱之為線程組或執(zhí)行組。
添加測試數(shù)據(jù)
正如普通用戶是不會一遍又一遍地搜索相同的關(guān)鍵字,也不會使用同一個測試帳戶在各處同時登錄那樣,我們的測試腳本也不應(yīng)該重復(fù)地使用相同的數(shù)據(jù)。如果多個虛擬用戶使用同一帳戶進行登錄,那么就可能導(dǎo)致其響應(yīng)被緩存,進而縮短響應(yīng)的時間,或增加錯誤率。對此,您需要將腳本修改為從某個CSV文件中獲取測試數(shù)據(jù),以增加真實的隨機性。
設(shè)置測試參數(shù)
測試參數(shù)往往能夠通過調(diào)整測試用戶數(shù)的激增與驟降,來改變用戶負載的時間變化趨勢,進而協(xié)助您繪制出虛擬用戶數(shù)與時間變化的曲線圖表。
在k6中體現(xiàn)的負載測試期間虛擬用戶的數(shù)量變化
設(shè)置失敗的判定標準
模擬真實用戶的一個重要環(huán)節(jié)便是發(fā)現(xiàn)有哪些因素會導(dǎo)致用戶訪問的失敗。您可以通過添加響應(yīng)驗證、檢查和閾值(包括響應(yīng)時間或錯誤率的閾值),將失敗的判定標準添加到測試腳本中。同時,您也可以根據(jù)實際情況,靈活地調(diào)整這些與性能相關(guān)的標準。
根據(jù)上述討論的要點,我對最初的k6基本腳本進行了修改,讓它更貼近真實的測試情況。在參考鏈接--https://gist.github.com/nicolevanderhoeven/fb74cd9769c8abf95eeb8765a49398cb中,也包含了一個帶有登錄憑據(jù)的CSV文件。
執(zhí)行負載測試
讓我們延用上面的k6腳本,并通過執(zhí)行如下命令,來觸發(fā)負載測試的運行:
- k6 run test.js
該命令將根據(jù)文件中已有的測試參數(shù)在本地執(zhí)行k6腳本。此類小型驗證性測試,通常被稱為震蕩測試(shakeout tests)。當(dāng)然,我們接下來會在基礎(chǔ)架構(gòu)上運行更加復(fù)雜的負載測試。
測試的真實性
當(dāng)您在數(shù)據(jù)中心的主機上運行負載測試時,由于測試與應(yīng)用服務(wù)器同屬一個網(wǎng)絡(luò),其響應(yīng)時間會比用戶真實體驗到的要快得多。因此,我們應(yīng)當(dāng)設(shè)法將負載生成器的位置,與用戶的物理位置相匹配。對此,在云端運行測試便是一種增加測試真實性的簡便方法,尤其是當(dāng)您的大多數(shù)最終用戶是在組織外部的時候。
針對上述例子,您可以通過鏈接--https://app.k6.io/account/register,注冊一個k6的云端帳戶(其中,前50個測試是免費的)。由于k6本身是開源的,因此您也可以在自己的云端基礎(chǔ)設(shè)施上運行它。當(dāng)然原生的k6云服務(wù)會更加直接且便于上手。
在擁有了帳戶之后,您可以通過鏈接--https://app.k6.io/account/api-token,復(fù)制API令牌,然后在終端中運行如下命令,以授權(quán)本地的k6運行您的帳戶:
- k6 login cloud –token
而成功地通過了身份驗證之后,您便可以選擇在云端運行如下命令了:
- k6 cloud test.js
下圖展示了k6執(zhí)行的負載測試結(jié)果。圖中的執(zhí)行模式(execution)則表明您是在云端運行該測試的。
由于您的測試默認會在美國Ashburn區(qū)域的k6 AWS賬戶中運行,因此您可以使用云端執(zhí)行選項(cloud execution options,請參見--https://k6.io/docs/cloud/creating-and-running-a-test/cloud-tests-from-the-cli#cloud-execution-options),將此設(shè)置按虛擬用戶的比例,指定到其他區(qū)域。
分析負載測試的結(jié)果和報告
盡管我們在邏輯上會將分析流程與執(zhí)行步驟相互分離,但是兩者實際上是重疊的。也就是說,上述k6的輸出截圖中其實已經(jīng)包含了指向k6云端儀表板的鏈接,可方便我們在測試運行過程中,實時地查看到測試的結(jié)果。這種實時監(jiān)控的測試方式可以讓用戶在出現(xiàn)問題時,及時地發(fā)現(xiàn)問題,并在必要時中止測試,以對其進行修復(fù)。如果測試是由多個負載生成器來執(zhí)行的,那么k6會有一個統(tǒng)一的儀表板,以展示測試的整體概況。
在k6Cloud中執(zhí)行負載測試后的結(jié)果示例
如果出現(xiàn)大量的錯誤,或者是響應(yīng)時間明確地表明某個組件無法處理負載的情況,我們應(yīng)當(dāng)立即中止測試,獲取必要的信息,以針對出現(xiàn)的瓶頸提出性能改進和解決方案。當(dāng)然,k6也會幫助用戶創(chuàng)建指向儀表板的可共享式鏈接(請參見--https://app.k6.io/runs/public/f6ad87cec7a24a8c82e46c816e67c4b3),以方便相關(guān)團隊通過協(xié)同“會診”,發(fā)掘出測試數(shù)據(jù)背后的真實原因。
雖然這些帶有測試結(jié)果的共享儀表板足以滿足敏捷團隊,但是對于某些項目而言,則可能需要正式的測試記錄總結(jié)報告。畢竟,負載測試的目的并不在于測試本身,而是對于結(jié)果的處理。我們需要向利益相關(guān)者清楚地傳達測試結(jié)果,以便大家更為有效地解決各種性能問題。
原文標題:An End-to-End Guide to Load Testing,作者: Nicole van der Hoeven
【51CTO譯稿,合作站點轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】