新一代服務(wù)器性能測試工具Gatling
21世紀(jì)是云的世紀(jì), 大規(guī)模云網(wǎng)已經(jīng)出現(xiàn)了,而且在未來幾年內(nèi)會得到高速發(fā)展,從而使得基于云的系統(tǒng)也會越來越多。如果要開發(fā)一款高性能的云系統(tǒng),服務(wù)器性能測試是一個必不可少的環(huán)節(jié)。今天,就來介紹一款新一代服務(wù)器性能測試工具Gatling。 一,什么是Gatling Gatling是一款基于Scala 開發(fā)的高性能服務(wù)器性能測試工具,它主要用于對服務(wù)器進(jìn)行負(fù)載等測試,并分析和測量服務(wù)器的各種性能指標(biāo)。Gatling主要用于測量基于HTTP的服務(wù)器,比如Web應(yīng)用程序,RESTful服務(wù)等,除此之外它擁有以下特點: 支持Akka Actors 和 Async IO,從而能達(dá)到很高的性能 支持實時生成Html動態(tài)輕量報表,從而使報表更易閱讀和進(jìn)行數(shù)據(jù)分析 支持DSL腳本,從而使測試腳本更易開發(fā)與維護(hù) 支持錄制并生成測試腳本,從而可以方便的生成測試腳本 支持導(dǎo)入HAR(Http Archive)并生成測試腳本 支持Maven,Eclipse,IntelliJ等,以便于開發(fā) 支持Jenkins,以便于進(jìn)行持續(xù)集成 支持插件,從而可以擴展其功能,比如可以擴展對其他協(xié)議的支持 開源免費 Gatling適用的場景包括:測試需求經(jīng)常改變,測試腳本需要經(jīng)常維護(hù);測試環(huán)境的客戶機性能不強,但又希望發(fā)揮硬件的極限性能;能對測試腳本進(jìn)行很好的版本管理,并通過CI進(jìn)行持續(xù)的性能測試;希望測試結(jié)果輕量易讀等。 相關(guān)廠商內(nèi)容 QCon上海技術(shù)訓(xùn)練營:OSGi、GitHub、Scrum深度培訓(xùn),10月29-31日與您相約,了解詳情! 2013年10月26日QClub大連站:大連軟件開發(fā)者大會 QCon上海2013“團(tuán)隊文化”專題:構(gòu)建持續(xù)前進(jìn)的團(tuán)隊文化、價值觀,工具與體系 GitHub中國上海Drinkup活動,就在QCon上海2013前夜,貝尼酒吧 QCon上海2013“游戲服務(wù)器實踐”專題:游戲服務(wù)器運維經(jīng)驗、架構(gòu)分享、性能策略 二,Gatling與JMeter JMeter是目前使用最為廣泛的服務(wù)器性能測試工具之一,它最大的特點就是擁有一套簡單易用的GUI,但它最大的缺點也是由于簡單易用導(dǎo)致它某些方面的不足,比如測試腳本(XML)不容易維護(hù)等。Gatling正是針對JMeter的劣勢做了大量改進(jìn),因此相較于 JMeter,Gatling擁有以下優(yōu)勢: 在并發(fā)性能方面,Gatling使用了Akka Actors和Async IO, 而JMeter則采用了一個用戶使用一個線程的方式 ,一旦并發(fā)線程過多,性能就急速下降,很難充分發(fā)揮硬件的能力。雖然兩個工具都是基于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個用戶并發(fā)下的測試結(jié)果。可以很明顯的看出,JMeter的并發(fā)量在300上下波動,最高達(dá)到400,最低達(dá)到200,而Gatling幾乎穩(wěn)定在300。由此可見Gatling性能的穩(wěn)定性。 在測試腳本方面,Gatling是Scala代碼,而JMeter主要是XML代碼。Gatling基于一套開源的Gatling DSL API,所以它的功能很容易擴展,也不需要使用者精通Scala語言。DSL的使用也更容易編寫出簡明,易讀性和維護(hù)性高的代碼,而且還可以使用版本工具進(jìn)行更有效的管理。因為性能測試應(yīng)該屬于系統(tǒng)發(fā)布流程中必不可少的一個步驟,所以測試腳本應(yīng)該和系統(tǒng)代碼一樣使用版本工具進(jìn)行統(tǒng)一管理。 在報表系統(tǒng)上,Gatling提供了一套輕量并且十分友好的Html報表系統(tǒng),使得用戶可以更為快速而方便地查看和分析數(shù)據(jù),相反,JMeter的報表系統(tǒng)卻十分笨重,且使用也不方便。
三,如何在項目中使用Gatling 對于Gatling這樣一個全新的服務(wù)器性能測試工具,是否能將它很好的運用到項目中并發(fā)揮其優(yōu)勢,這個是一個困擾測試決策者的問題。下面我將結(jié)合在一個真實項目中使用和部署Gatling的經(jīng)驗來解答這個問題。 搭建測試環(huán)境 在一個大型的Web項目中,測試環(huán)境的搭建是項目測試工作開始的第一步,也是最為關(guān)鍵的一步,因為測試環(huán)境直接影響到測試成本和測試結(jié)果。由于這個項目對于性能的要求并不是很高,我們經(jīng)過討論和分析,決定選取虛擬機作為測試平臺。這就意味著被測系統(tǒng)以及測試客戶端可以使用的硬件資源比如CPU和內(nèi)存十分有限,因此需要測試工具能充分使用有限的資源發(fā)揮最大的性能。 進(jìn)行負(fù)載測試 為了快速實現(xiàn)測試腳本,我首先選擇了使用Gatling錄制功能進(jìn)行腳本錄制,成功錄制以后會在指定的“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個用戶 沒有檢測點 沒有邏輯分層 因此,它并不能用于真正的性能測試。對于這樣的原始代碼,我們需要進(jìn)行大量的重構(gòu),使代碼擁有很好的可讀性和可維護(hù)性。 首先我們要進(jìn)行分層處理: 對于錄制代碼段1,需要建立一個Header類來管理所有HTTP Header,這里使用“Headers.scala”,在錄制代碼段1中只給出了“headers_1”,實際的腳本包含了大量的Header。 對于錄制代碼段2,需要將測試場景和測試控制分開,每一個測試場景使用一個文件來保存,代碼段2所示的場景使用“UploadImageScenario.scala”來保存。主控腳本也需要分離出來存入“MainSimulation.scala”,通過調(diào)用不同的測試場景的腳本,從而可以復(fù)用HTTP的配置選項,比如: val httpProtocol = http .baseURL("http:// :10.17.7.3") 其次,我們還需要增加多用戶的支持: 多用戶數(shù)據(jù)的讀入,其中“user_credentials.csv”存儲的就是用戶名和密碼.feed(csv("user_credentials.csv")).exec(http("request_login").post("""/customer/login""").param("""username""", """${username}""").param("""password", "${password}""")
設(shè)置多用戶的值。由于我們使用的是虛擬機,所以經(jīng)過測試,確定為400用戶并發(fā)。 setUp(LoginScenario.loginScn.inject(ramp(400 users) over(60 seconds))). protocols(httpProtocol) 最后,我們還要增加檢測點,使用check,find,status等函數(shù)進(jìn)行檢測,下面的代碼檢測了用戶登出的時候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è)計測試系統(tǒng)并進(jìn)行測試案例的開發(fā)。 項目采取了敏捷方法進(jìn)行開發(fā),所以系統(tǒng)的一些功能在開發(fā)過程中會出現(xiàn)頻繁改動,導(dǎo)致測試場景和測試腳本也會隨之發(fā)生改變,因此,測試腳本的可讀性和可維護(hù)性對于我們來說就非常重要。當(dāng)某個功能改變之后,使用Gatling腳本就能十分方便的進(jìn)行閱讀和重構(gòu)。比如對于添加user的功能,第一版只需要能添加user即可(見添加user代碼1),而在下一版中,則要求在添加user時可以選擇該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]""", """user@gmail.com""").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]""", """user@gmail.com""").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 項目發(fā)布后,若項目功能發(fā)生改變,我們也可以使用Gatling進(jìn)行持續(xù)的性能回歸測試,保證系統(tǒng)性能不會因為某次修改導(dǎo)致非預(yù)期的降低。如果降低了,就要進(jìn)行及時的調(diào)查,修復(fù)或者是調(diào)整,保證性能一直在預(yù)期的可控范圍內(nèi)。 測試報表 Gatling測試報表基于HTML,并且在測試過程中業(yè)已生成,所以打開速度很快。而且,當(dāng)把鼠標(biāo)移動到不同數(shù)據(jù)軸上時,都會有彈出框顯示這個點上詳細(xì)的測試數(shù)據(jù)信息。這種動態(tài)顯示數(shù)據(jù)的方式非常方便查看和分析數(shù)據(jù)。考慮到項目真實數(shù)據(jù)的不便,我將通過Gatling官方網(wǎng)站給出的示例報表進(jìn)行說明。 Gatling的報表分為兩類:GLOBAL和DETAILS,其中GLOBAL主要是請求相關(guān)的統(tǒng)計數(shù)據(jù),比如每秒請求數(shù),請求成功與失敗數(shù)等;其中DETAILS主要是請求時間相關(guān)的統(tǒng)計數(shù)據(jù),比如請求響應(yīng)時間,請求響應(yīng)延遲時間等。圖4 每秒請求數(shù) 當(dāng)鼠標(biāo)放到圖中任何一個點的時候,對應(yīng)時間點上請求的詳細(xì)數(shù)據(jù)就會以圖中白色的彈出框的方式進(jìn)行顯示。在下面的請求響應(yīng)延遲時間圖里面也有同樣的功能。圖5 請求響應(yīng)延遲時間 3,與CI的集成 項目的CI系統(tǒng)選用的是Jenkins,因為Jenkins有Gatling的插件,所以通過這個插件可以在Jenkins上直接查看Gatling的測試結(jié)果,如圖6所示。圖6 Jenkins Gatling插件 我們還把生成的報表存檔到每個Build里面,這樣就可以在每個Build中獲得那次測試的所有報表。 更多類型的測試 其他類型的HTTP服務(wù)器性能測試,比如瞬間壓力測試,耐久性測試等,都十分適合使用Gatling。 四,未來的Gatling Gatling發(fā)布的時間雖然不長,但憑借其優(yōu)良的性能,DSL模式的腳本,輕量友好的報表系統(tǒng)在眾多服務(wù)器性能測試工具中脫穎而出。在2013年5月發(fā)布的ThoughtWorks技術(shù)雷達(dá)中,Gatling被列入了ADOPT,并在一些ThoughtWorks項目中得到了實際的運用。不過,Gatling還是存在一些問題,比如不支持分布式模型;默認(rèn)只支持HTTP,對于其他協(xié)議需要自己動手進(jìn)行擴展;報表種類也不是很豐富 。倘若Gatling 能在這幾方面有所突破,那么它必將成為新一代服務(wù)器性能測試工具中的殺手锏。
三,如何在項目中使用Gatling
對于Gatling這樣一個全新的服務(wù)器性能測試工具,是否能將它很好的運用到項目中并發(fā)揮其優(yōu)勢,這個是一個困擾測試決策者的問題。下面我將結(jié)合在一個真實項目中使用和部署Gatling的經(jīng)驗來解答這個問題。
搭建測試環(huán)境
在一個大型的Web項目中,測試環(huán)境的搭建是項目測試工作開始的第一步,也是最為關(guān)鍵的一步,因為測試環(huán)境直接影響到測試成本和測試結(jié)果。由于這個項目對于性能的要求并不是很高,我們經(jīng)過討論和分析,決定選取虛擬機作為測試平臺。這就意味著被測系統(tǒng)以及測試客戶端可以使用的硬件資源比如CPU和內(nèi)存十分有限,因此需要測試工具能充分使用有限的資源發(fā)揮最大的性能。
進(jìn)行負(fù)載測試
為了快速實現(xiàn)測試腳本,我首先選擇了使用Gatling錄制功能進(jìn)行腳本錄制,成功錄制以后會在指定的“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個用戶
沒有檢測點
沒有邏輯分層
因此,它并不能用于真正的性能測試。對于這樣的原始代碼,我們需要進(jìn)行大量的重構(gòu),使代碼擁有很好的可讀性和可維護(hù)性。
首先我們要進(jìn)行分層處理:
對于錄制代碼段1,需要建立一個Header類來管理所有HTTP Header,這里使用“Headers.scala”,在錄制代碼段1中只給出了“headers_1”,實際的腳本包含了大量的Header。
對于錄制代碼段2,需要將測試場景和測試控制分開,每一個測試場景使用一個文件來保存,代碼段2所示的場景使用“UploadImageScenario.scala”來保存。主控腳本也需要分離出來存入“MainSimulation.scala”,通過調(diào)用不同的測試場景的腳本,從而可以復(fù)用HTTP的配置選項,比如:
val httpProtocol = http
.baseURL("http:// :10.17.7.3")
其次,我們還需要增加多用戶的支持:
多用戶數(shù)據(jù)的讀入,其中“user_credentials.csv”存儲的就是用戶名和密碼
.feed(csv("user_credentials.csv")) .exec(http("request_login") .post("""/customer/login""") .param("""username""", """${username}""") .param("""password", "${password}""") |
設(shè)置多用戶的值。由于我們使用的是虛擬機,所以經(jīng)過測試,確定為400用戶并發(fā)。
setUp(LoginScenario.loginScn.inject(ramp(400 users) over(60 seconds))).
protocols(httpProtocol)
最后,我們還要增加檢測點,使用check,find,status等函數(shù)進(jìn)行檢測,下面的代碼檢測了用戶登出的時候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è)計測試系統(tǒng)并進(jìn)行測試案例的開發(fā)。
項目采取了敏捷方法進(jìn)行開發(fā),所以系統(tǒng)的一些功能在開發(fā)過程中會出現(xiàn)頻繁改動,導(dǎo)致測試場景和測試腳本也會隨之發(fā)生改變,因此,測試腳本的可讀性和可維護(hù)性對于我們來說就非常重要。當(dāng)某個功能改變之后,使用Gatling腳本就能十分方便的進(jìn)行閱讀和重構(gòu)。比如對于添加user的功能,第一版只需要能添加user即可(見添加user代碼1),而在下一版中,則要求在添加user時可以選擇該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]""", """user@gmail.com""") .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]""", """user@gmail.com""") .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
項目發(fā)布后,若項目功能發(fā)生改變,我們也可以使用Gatling進(jìn)行持續(xù)的性能回歸測試,保證系統(tǒng)性能不會因為某次修改導(dǎo)致非預(yù)期的降低。如果降低了,就要進(jìn)行及時的調(diào)查,修復(fù)或者是調(diào)整,保證性能一直在預(yù)期的可控范圍內(nèi)。
測試報表
Gatling測試報表基于HTML,并且在測試過程中業(yè)已生成,所以打開速度很快。而且,當(dāng)把鼠標(biāo)移動到不同數(shù)據(jù)軸上時,都會有彈出框顯示這個點上詳細(xì)的測試數(shù)據(jù)信息。這種動態(tài)顯示數(shù)據(jù)的方式非常方便查看和分析數(shù)據(jù)。考慮到項目真實數(shù)據(jù)的不便,我將通過Gatling官方網(wǎng)站給出的示例報表進(jìn)行說明。
Gatling的報表分為兩類:GLOBAL和DETAILS,其中GLOBAL主要是請求相關(guān)的統(tǒng)計數(shù)據(jù),比如每秒請求數(shù),請求成功與失敗數(shù)等;其中DETAILS主要是請求時間相關(guān)的統(tǒng)計數(shù)據(jù),比如請求響應(yīng)時間,請求響應(yīng)延遲時間等。
圖4 每秒請求數(shù)
當(dāng)鼠標(biāo)放到圖中任何一個點的時候,對應(yīng)時間點上請求的詳細(xì)數(shù)據(jù)就會以圖中白色的彈出框的方式進(jìn)行顯示。在下面的請求響應(yīng)延遲時間圖里面也有同樣的功能。
圖5 請求響應(yīng)延遲時間
3,與CI的集成
項目的CI系統(tǒng)選用的是Jenkins,因為Jenkins有Gatling的插件,所以通過這個插件可以在Jenkins上直接查看Gatling的測試結(jié)果,如圖6所示。
圖6 Jenkins Gatling插件
我們還把生成的報表存檔到每個Build里面,這樣就可以在每個Build中獲得那次測試的所有報表。
更多類型的測試
其他類型的HTTP服務(wù)器性能測試,比如瞬間壓力測試,耐久性測試等,都十分適合使用Gatling。
四,未來的Gatling
Gatling發(fā)布的時間雖然不長,但憑借其優(yōu)良的性能,DSL模式的腳本,輕量友好的報表系統(tǒng)在眾多服務(wù)器性能測試工具中脫穎而出。在2013年5月發(fā)布的ThoughtWorks技術(shù)雷達(dá)中,Gatling被列入了ADOPT,并在一些ThoughtWorks項目中得到了實際的運用。不過,Gatling還是存在一些問題,比如不支持分布式模型;默認(rèn)只支持HTTP,對于其他協(xié)議需要自己動手進(jìn)行擴展;報表種類也不是很豐富 。倘若Gatling 能在這幾方面有所突破,那么它必將成為新一代服務(wù)器性能測試工具中的殺手锏。
posted on 2013-10-24 10:52 順其自然EVO 閱讀(342) 評論(0) 編輯 收藏 所屬分類: 性能測試