性能測試之新一代服務(wù)器性能測試工具Gatling

21 世紀(jì)是云的世紀(jì), 大規(guī)模云網(wǎng)已經(jīng)出現(xiàn)了,而且在未來幾年內(nèi)會(huì)得到高速發(fā)展,從而使得基于云的系統(tǒng)也會(huì)越來越多。如果要開發(fā)一款高性能的云系統(tǒng),服務(wù)器性能測試是一個(gè)必不可少的環(huán)節(jié) 。今天,就來介紹一款新一代服務(wù)器性能測試工具 Gatling。
??
? ?
一,什么是 Gatling
Gatling 是一款基于 Scala 開發(fā)的高性能服務(wù)器性能測試工具,它主要用于對(duì)服務(wù)器進(jìn)行負(fù)載等測試,并分析和測量服務(wù)器的各種性能指標(biāo)。Gatling 主要用于測量基于 HTTP 的服務(wù)器,比如 Web 應(yīng)用程序,RESTful 服務(wù)等 ,除此之外它擁有以下特點(diǎn):
支持 Akka Actors 和 Async IO,從而能達(dá)到很高的性能
支持實(shí)時(shí)生成 Html 動(dòng)態(tài)輕量報(bào)表,從而使報(bào)表更易閱讀和進(jìn)行數(shù)據(jù)分析
支持 DSL 腳本,從而使測試腳本更易開發(fā)與維護(hù)
支持錄制并生成測試腳本,從而可以方便的生成測試腳本
支持導(dǎo)入 HAR(Http Archive)并生成測試腳本
支持 Maven,Eclipse,IntelliJ 等,以便于開發(fā)
支持 Jenkins,以便于進(jìn)行持續(xù)集成
支持插件,從而可以擴(kuò)展其功能,比如可以擴(kuò)展對(duì)其他協(xié)議的支持
開源免費(fèi) Gatling 適用的場景包括:測試需求經(jīng)常改變,測試腳本需要經(jīng)常維護(hù);測試環(huán)境的客戶機(jī)性能不強(qiáng),但又希望發(fā)揮硬件的極限性能;能對(duì)測試腳本進(jìn)行很好的版本管理,并通過 CI 進(jìn)行持續(xù)的性能測試;希望測試結(jié)果輕量易讀等。
??
? ?
二,Gatling 與 JMeter
JMeter 是目前使用最為廣泛的服務(wù)器性能測試工具之一,它最大的特點(diǎn)就是擁有一套簡單易用的 GUI,但它最大的缺點(diǎn)也是由于簡單易用導(dǎo)致它某些方面的不足,比如測試腳本(XML)不容易維護(hù)等。Gatling 正是針對(duì) JMeter 的劣勢做了大量改進(jìn),因此相較于 JMeter,Gatling 擁有以下優(yōu)勢:
在并發(fā)性能方面,Gatling 使用了 Akka Actors 和 Async IO, 而 JMeter 則采用了一個(gè)用戶使用一個(gè)線程的方式 ,一旦并發(fā)線程過多,性能就急速下降,很難充分發(fā)揮硬件的能力。雖然兩個(gè)工具都是基于 JVM 的,但是 Actors 模型的性能在高并發(fā)的情況下性能大大優(yōu)于 Threads,從而使得 Gatling 在更少的內(nèi)存和 CPU 的情況下可以提供同樣的測試能力,降低了測試成本。圖 1 和圖 2 分別展現(xiàn)了二者在并發(fā)性能方面的表現(xiàn)。
圖 1,JMeter 2.8
圖 2,Gatling 1.3.2圖片,測試環(huán)境和測試腳本參見:https://github.com/excilys/gatling/wiki/Benchmarks
其中圖 1 和圖 2 分別是 JMeter 和 Gatling 在 300 個(gè)用戶并發(fā)下的測試結(jié)果。可以很明顯的看出,JMeter 的并發(fā)量在 300 上下波動(dòng),最高達(dá)到 400,最低達(dá)到 200,而 Gatling 幾乎穩(wěn)定在 300。由此可見 Gatling 性能的穩(wěn)定性。
在測試腳本方面,Gatling 是 Scala 代碼,而 JMeter 主要是 XML 代碼。Gatling 基于一套開源的 Gatling DSL API,所以它的功能很容易擴(kuò)展,也不需要使用者精通 Scala 語言。DSL 的使用也更容易編寫出簡明,易讀性和維護(hù)性高的代碼,而且還可以使用版本工具進(jìn)行更有效的管理。因?yàn)樾阅軠y試應(yīng)該屬于系統(tǒng)發(fā)布流程中必不可少的一個(gè)步驟,所以測試腳本應(yīng)該和系統(tǒng)代碼一樣使用版本工具進(jìn)行統(tǒng)一管理。
在報(bào)表系統(tǒng)上,Gatling 提供了一套輕量并且十分友好的 Html 報(bào)表系統(tǒng),使得用戶可以更為快速而方便地查看和分析數(shù)據(jù),相反,JMeter 的報(bào)表系統(tǒng)卻十分笨重,且使用也不方便。
??
? ?
三,如何在項(xiàng)目中使用 Gatling
對(duì)于 Gatling 這樣一個(gè)全新的服務(wù)器性能測試工具,是否能將它很好的運(yùn)用到項(xiàng)目中并發(fā)揮其優(yōu)勢,這個(gè)是一個(gè)困擾測試決策者的問題 。下面我將結(jié)合在一個(gè)真實(shí)項(xiàng)目中使用和部署 Gatling 的經(jīng)驗(yàn)來解答這個(gè)問題。
? ?
1,搭建測試環(huán)境
在一個(gè)大型的 Web 項(xiàng)目中,測試環(huán)境的搭建是項(xiàng)目測試工作開始的第一步,也是最為關(guān)鍵的一步,因?yàn)闇y試環(huán)境直接影響到測試成本和測試結(jié)果。由于這個(gè)項(xiàng)目對(duì)于性能的要求并不是很高,我們經(jīng)過討論和分析,決定選取虛擬機(jī)作為測試平臺(tái)。這就意味著被測系統(tǒng)以及測試客戶端可以使用的硬件資源比如 CPU 和內(nèi)存十分有限,因此需要測試工具能充分使用有限的資源發(fā)揮最大的性能。
? ?
2,進(jìn)行負(fù)載測試
為了快速實(shí)現(xiàn)測試腳本,我首先選擇了使用 Gatling 錄制功能進(jìn)行腳本錄制,成功錄制以后會(huì)在指定的“Output folder”目錄下面生成你指定“Class Name”為名字的腳本,見圖 3。
圖 3,Gatling Recorder
根據(jù)圖 3 的配置,錄制好的腳本存放在/Users/twer/work/gatling/user-files/simulations/Common/MyRecordedSimulation.scala。生成的部分腳本代碼如下:
class MyRecordedSimulation extends Simulation { ?val httpProtocol = http ? ?.baseURL("http:// :10.17.7.3") ? ?.acceptHeader("image/png,image/*;q=0.8,*/*;q=0.5") ? ?.acceptEncodingHeader("gzip, deflate") ? ?.acceptLanguageHeader("en-US,en;q=0.5") ? ?.connection("keep-alive") ? ?.userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:22.0) Gecko/20100101 Firefox/22.0") val headers_1 = Map( ? ?"""Accept""" -> """text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8""", ? ?"""If-None-Match""" -> """"a3ef335152d5532e2297bd8ad288f3f9"""")
錄制代碼段 1
.exec(http("request_21")
? ?.get("""/customer/images/new?app_dialog=true&dialog=true""")
? ?.headers(headers_18))
?.pause(6)
?.exec(http("request_22")
? ?.get("""/customer/images?_=1374400463122""")
? ?.headers(headers_19))
?.pause(165 milliseconds)
?.exec(http("request_23")
? ?.get("""/Users/twer/work/gatling/user-files/simulations/testdata/test1.png""")
? ?.headers(headers_20)
? ?.check(status.is(500)))
?.pause(2)
?.exec(http("request_24")
? ?.get("""/customer/images?view=list"""))
?.pause(86 milliseconds)
……
setUp(scn.inject(atOnce(1 user))).protocols(httpProtocol)
錄制代碼段 2
錄制出來的腳本擁有很多局限性:
只支持 1 個(gè)用戶
沒有檢測點(diǎn)
沒有邏輯分層
因此,它并不能用于真正的性能測試。對(duì)于這樣的原始代碼,我們需要進(jìn)行大量的重構(gòu),使代碼擁有很好的可讀性和可維護(hù)性。
首先我們要進(jìn)行分層處理:
對(duì)于錄制代碼段 1,需要建立一個(gè) Header 類來管理所有 HTTP Header,這里使用“Headers.scala”,在錄制代碼段 1 中只給出了“headers_1”,實(shí)際的腳本包含了大量的 Header。
對(duì)于錄制代碼段 2,需要將測試場景和測試控制分開,每一個(gè)測試場景使用一個(gè)文件來保存, 代碼段 2 所示的場景使用“UploadImageScenario.scala”來保存。主控腳本也需要分離出來存入“MainSimulation.scala”,通過調(diào)用不同的測試場景的腳本,從而可以復(fù)用 HTTP 的配置選項(xiàng),比如:
val httpProtocol = http ? ?.baseURL("http:// :10.17.7.3")
其次,我們還需要增加多用戶的支持:
多用戶數(shù)據(jù)的讀入,其中“user_credentials.csv”存儲(chǔ)的就是用戶名和密碼
.feed(csv("user_credentials.csv")) ?.exec(http("request_login") ? ?.post("""/customer/login""") ? ?.param("""username""", """${username}""") ? ?.param("""password", "${password}""")
設(shè)置多用戶的值。由于我們使用的是虛擬機(jī),所以經(jīng)過測試,確定為 400 用戶并發(fā)。
setUp(LoginScenario.loginScn.inject(ramp(400 users) over(60 seconds))).protocols(httpProtocol)
最后,我們還要增加檢測點(diǎn),使用 check,find,status 等函數(shù)進(jìn)行檢測,下面的代碼檢測了用戶登出的時(shí)候 HTTP Response Status 是否為 302:
exec(http("request_logout") ?.get(("""/customer/logout""") ?.headers(headers_logout) ?.check(status.is(302)))
當(dāng)然,如果測試人員熟悉 Gatling DSL API,我們也可以不用錄制代碼再進(jìn)行重構(gòu),而是直接設(shè)計(jì)測試系統(tǒng)并進(jìn)行測試案例的開發(fā)。
項(xiàng)目采取了敏捷方法進(jìn)行開發(fā),所以系統(tǒng)的一些功能在開發(fā)過程中會(huì)出現(xiàn)頻繁改動(dòng),導(dǎo)致測試場景和測試腳本也會(huì)隨之發(fā)生改變,因此,測試腳本的可讀性和可維護(hù)性對(duì)于我們來說就非常重要。當(dāng)某個(gè)功能改變之后,使用 Gatling 腳本就能十分方便的進(jìn)行閱讀和重構(gòu)。比如對(duì)于添加 user 的功能,第一版只需要能添加 user 即可(見添加 user 代碼 1),而在下一版中,則要求在添加 user 時(shí)可以選擇該 user 具有那些權(quán)限(見添加 user 代碼 2),代碼如下:
.exec(http("request_add_user") ?.post("""/customer/users""") ?.headers(headers_user) ?.param("""utf8""", """?""") ?.param("""user[username]""", """user2""") ?.param("""user[email]""", """[email protected]""") ?.param("""user[password]""", """user2""") ?.param("""user[password_confirmation]""", """user2""")
添加 user 代碼 1
.exec(http("request_add_user") ?.post("""/customer/users""") ?.headers(headers_user) ?.param("""utf8""", """?""") ?.param("""user[username]""", """user2""") ?.param("""user[email]""", """[email protected]""") ?.param("""user[password]""", """user2""") ?.param("""user[password_confirmation]""", """user2""") ?.param("""user[plugins][]""", """customer_dashboard""") ?.param("""user[plugins][]""", """customer_files""") ?.param("""user[plugins][]""", """customer_images""") ?.param("""user[plugins][]""", """customer_pages"""))
添加 user 代碼 2
項(xiàng)目發(fā)布后,若項(xiàng)目功能發(fā)生改變,我們也可以使用 Gatling 進(jìn)行持續(xù)的性能回歸測試,保證系統(tǒng)性能不會(huì)因?yàn)槟炒涡薷膶?dǎo)致非預(yù)期的降低。如果降低了,就要進(jìn)行及時(shí)的調(diào)查,修復(fù)或者是調(diào)整,保證性能一直在預(yù)期的可控范圍內(nèi)。
? ?
3,測試報(bào)表
Gatling 測試報(bào)表基于 HTML,并且在測試過程中業(yè)已生成,所以打開速度很快。而且,當(dāng)把鼠標(biāo)移動(dòng)到不同數(shù)據(jù)軸上時(shí),都會(huì)有彈出框顯示這個(gè)點(diǎn)上詳細(xì)的測試數(shù)據(jù)信息。這種動(dòng)態(tài)顯示數(shù)據(jù)的方式非常方便查看和分析數(shù)據(jù)。考慮到項(xiàng)目真實(shí)數(shù)據(jù)的不便,我將通過 Gatling 官方網(wǎng)站給出的示例報(bào)表進(jìn)行說明。
Gatling 的報(bào)表分為兩類:GLOBAL 和 DETAILS,其中 GLOBAL 主要是請(qǐng)求相關(guān)的統(tǒng)計(jì)數(shù)據(jù),比如每秒請(qǐng)求數(shù),請(qǐng)求成功與失敗數(shù)等;其中 DETAILS 主要是請(qǐng)求時(shí)間相關(guān)的統(tǒng)計(jì)數(shù)據(jù),比如請(qǐng)求響應(yīng)時(shí)間,請(qǐng)求響應(yīng)延遲時(shí)間等。
圖 4 每秒請(qǐng)求數(shù),圖片來自 http://gatling-tool.org/sample/req_home.html
當(dāng)鼠標(biāo)放到圖中任何一個(gè)點(diǎn)的時(shí)候,對(duì)應(yīng)時(shí)間點(diǎn)上請(qǐng)求的詳細(xì)數(shù)據(jù)就會(huì)以圖中白色的彈出框的方式進(jìn)行顯示。在下面的請(qǐng)求響應(yīng)延遲時(shí)間圖里面也有同樣的功能。
圖 5 請(qǐng)求響應(yīng)延遲時(shí)間,圖片來自 http://gatling-tool.org/sample/index.html
? ?
4,與 CI 的集成
項(xiàng)目的 CI 系統(tǒng)選用的是 Jenkins,因?yàn)?Jenkins 有 Gatling 的插件,所以通過這個(gè)插件可以在 Jenkins 上直接查看 Gatling 的測試結(jié)果,如圖 6 所示。
圖 6 Jenkins Gatling 插件,圖片來自:https://wiki.jenkins-ci.org/display/JENKINS/Gatling+Plugin
我們還把生成的報(bào)表存檔到每個(gè) Build 里面,這樣就可以在每個(gè) Build 中獲得那次測試的所有報(bào)表。
? ?
5,更多類型的測試
其他類型的 HTTP 服務(wù)器性能測試,比如瞬間壓力測試,耐久性測試等, 都十分適合使用 Gatling。
??
? ?
四,未來的 Gatling
Gatling 發(fā)布的時(shí)間雖然不長,但憑借其優(yōu)良的性能,DSL 模式的腳本,輕量友好的報(bào)表系統(tǒng)在眾多服務(wù)器性能測試工具中脫穎而出。在 2013 年 5 月發(fā)布的 ThoughtWorks 技術(shù)雷達(dá)中,Gatling 被列入了 ADOPT,并在一些 ThoughtWorks 項(xiàng)目中得到了實(shí)際的運(yùn)用。不過,Gatling 還是存在一些問題,比如不支持分布式模型;默認(rèn)只支持 HTTP,對(duì)于其他協(xié)議需要自己動(dòng)手進(jìn)行擴(kuò)展;報(bào)表種類也不是很豐富 。倘若 Gatling 能在這幾方面有所突破,那么它必將成為新一代服務(wù)器性能測試工具中的殺手锏。
測試開發(fā)棧
軟件測試開發(fā)合并必將是趨勢,不懂開發(fā)的測試、不懂測試的開發(fā)都將可能被逐漸替代,因此前瞻的技術(shù)儲(chǔ)備和知識(shí)積累是我們以后在職場和行業(yè)脫穎而出的法寶,期望我們的經(jīng)驗(yàn)和技術(shù)分享能讓你每天都成長和進(jìn)步,早日成為測試開發(fā)棧上的技術(shù)大牛~~
長按二維碼/微信掃描關(guān)注
互聯(lián)網(wǎng)測試開發(fā)一站式全棧分享平臺(tái)
