gatling 使用_使用Gatling + Gradle + Jenkins Pipeline为您的JAX-RS(和JavaEE)应用程序进行连续压力测试...
gatling 使用
在這篇文章中,我將解釋如何使用Gatling項(xiàng)目為您的JAX-RS Java EE端點(diǎn)編寫壓力測試,以及如何將它們與Gradle和Jenkins Pipeline集成,因此,除了進(jìn)行簡單的壓力測試外,您還可以使用以下方法: 連續(xù)壓力測試,其中每個(gè)提交可能會(huì)自動(dòng)觸發(fā)此類測試,并提供自動(dòng)斷言和每個(gè)執(zhí)行的更重要的圖形反饋,因此您可以監(jiān)視應(yīng)用程序中性能的變化。
首先要開發(fā)的是JAX-RS JavaEE服務(wù):
@Path("/planet") @Singleton @Lock(LockType.READ) public class PlanetResources {@InjectSwapiGateway swapiGateway;@InjectPlanetService planetService;@Inject@AverageFormatterDecimalFormat averageFormatter;@GET@Path("/orbital/average")@Produces(MediaType.TEXT_PLAIN)@Asynchronouspublic void calculateAverageOfOrbitalPeriod(@Suspended final AsyncResponse response) {// Timeout controlresponse.setTimeoutHandler(asyncResponse -> asyncResponse.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE).entity("TIME OUT !").build()));response.setTimeout(30, TimeUnit.SECONDS);try {// SwapiGateway is an interface to swapi.co (Star Wars API)JsonObject planets = swapiGateway.getAllPlanets();final JsonArray results = planets.getJsonArray("results");// Make some calculations with the result retrieved from swapi.codouble average = planetService.calculateAverageOfOrbitalPeriod(results);final Response averageResponse = Response.ok(averageFormatter.format(average)).build();response.resume(averageResponse);} catch(Throwable e) {response.resume(e);}} }沒什么特別的,這是一個(gè)異步的JAX-RS端點(diǎn),它連接到swapi.co網(wǎng)站,檢索“星球大戰(zhàn)”行星的所有信息,計(jì)算出軌道周期的平均值,最后以文本形式返回。 為了簡單起見,我不會(huì)向您展示所有其他類,但是它們非常簡單,在文章結(jié)尾,我將為您提供github存儲(chǔ)庫。
該應(yīng)用程序打包在war文件中,并部署到應(yīng)用程序服務(wù)器中。 在這種情況下,將部署到官方Apache TomEE Docker映像內(nèi)部署的Apache TomEE 7 。
下一步是使用Gatling依賴項(xiàng)配置Gradle構(gòu)建腳本。 由于Gatling是用Scala編寫的,因此您需要使用Scala插件。
apply plugin: 'java' apply plugin: 'scala'def gatlingVersion = "2.1.7"dependencies {compile "org.scala-lang:scala-library:2.11.7"testCompile "io.gatling:gatling-app:${gatlingVersion}"testCompile "io.gatling.highcharts:gatling-charts-highcharts:${gatlingVersion}" }之后,是時(shí)候編寫我們的第一個(gè)壓力測試了。 重要的是要注意,為加特林編寫壓力測試正在使用提供的DSL編寫Scala類。 即使對(duì)于從未看過Scala的人來說,如何使用它也非常直觀。
因此,創(chuàng)建一個(gè)名為src / test / scala的目錄,并創(chuàng)建一個(gè)具有下一個(gè)內(nèi)容的名為AverageOrbitalPeriodSimulation.scala的新類:
package org.starwarsimport io.gatling.core.Predef._ import io.gatling.http.Predef._ import scala.concurrent.duration._ import scala.util.Properties// Extends from Simulation class AverageOrbitalPeriodSimulation extends Simulation {// Gets the base URL where our service is running from environment/system propertyval LOCATION_PROPERTY = "starwars_planets_url";val location = Properties.envOrElse(LOCATION_PROPERTY, Properties.propOrElse(LOCATION_PROPERTY, "http://localhost:8080/"))// configures the base URLval conf = http.baseURL(location)// defines the scenario to run, which in this case is a GET to endpoint defined in JAX-RS serviceval scn = scenario("calculate average orbital period").exec(http("get average orbital period").get("rest/planet/orbital/average")).pause(1)// instead of simulating 10 users at once, it adds gradullay the 10 users during 3 seconds// asserts that there is no failing requests and that at max each request takes less than 3 secondssetUp(scn.inject(rampUsers(10).over(3 seconds))).protocols(conf).assertions(global.successfulRequests.percent.is(100), global.responseTime.max.lessThan(3000)) }每個(gè)模擬都必須擴(kuò)展模擬對(duì)象。 此模擬從starwars_planets_url環(huán)境或系統(tǒng)屬性獲取服務(wù)的基本URL,它創(chuàng)建指向JAX-RS中定義的端點(diǎn)的方案,最后在3秒鐘內(nèi)它將逐漸添加用戶,直到同時(shí)運(yùn)行10個(gè)用戶。 僅在所有請(qǐng)求在3秒內(nèi)成功通過后,測試才能通過。
現(xiàn)在我們需要運(yùn)行此測試。 您會(huì)注意到這不是JUnit測試,因此您無法執(zhí)行Run As JUnit測試。 您需要做的是使用Gatling提供的可運(yùn)行類,該類要求您將模擬類作為參數(shù)傳遞。 使用Gradle確實(shí)很容易做到。
task runLoadTest(type: JavaExec) {// before runnign the task we need to compile the testsdependsOn testClassesdescription = 'Stress Test Calculating Orbital Period'classpath = sourceSets.main.runtimeClasspath + sourceSets.test.runtimeClasspath// if starwars_planets_url is not provided we add the DOCKER_HOST one automaticallydef starwarsUrl;if (!System.env.containsKey('starwars_planets_url') && !System.properties.containsKey('starwars_planets_url')) {if (System.env.containsKey('DOCKER_HOST')) {starwarsUrl = System.env.DOCKER_HOST.replace("tcp", "http").replace("2376", "9090") + "/starwars/"} else {starwarsUrl = "http://localhost:8080/starwars/"}}jvmArgs = [ "-Dgatling.core.directory.binaries=${sourceSets.test.output.classesDir.toString()}" ]// Means that the url has been calculated here and we set itif (starwarsUrl != null) {environment["starwars_planets_url"] = starwarsUrl}// Gatling applicationmain = "io.gatling.app.Gatling"// Specify the simulation to run and outputargs = ["--simulation", "org.starwars.AverageOrbitalPeriodSimulation","--results-folder", "${buildDir}/reports/gatling-results","--binaries-folder", sourceSets.test.output.classesDir.toString(),"--output-name", "averageorbitalperiodsimulation","--bodies-folder", sourceSets.test.resources.srcDirs.toList().first().toString() + "/gatling/bodies",] }// when running test task we want to execute the Gatling test test.dependsOn runLoadTest我們正在定義JavaExec類型的Gradle任務(wù),因?yàn)槲覀兿胍氖沁\(yùn)行一個(gè)可運(yùn)行的類。 然后,通過自動(dòng)檢測是否未設(shè)置starwars_planets_url,將測試運(yùn)行到已安裝Docker的計(jì)算機(jī)上,因此我們可以使開發(fā)人員的工作更加輕松。
最后,如果需要,我們將覆蓋環(huán)境變量,我們?yōu)榭蛇\(yùn)行類設(shè)置必需的屬性,并配置Gradle在每次執(zhí)行測試任務(wù)(./gradlew test)時(shí)執(zhí)行此任務(wù)。
如果運(yùn)行它,您可能會(huì)看到來自Gatling的一些輸出消息,以及所有類似如下的消息:請(qǐng)打開以下文件: /Users/…./stress-test/build/reports/gatlingresults / averageorbitalperiodsimulation-1459413095563 / index。 html ,這是您獲取報(bào)告的地方。 請(qǐng)注意,在目錄末尾附加了一個(gè)隨機(jī)數(shù),這很重要,因?yàn)樯院笪覀儠?huì)看到。 該報(bào)告可能如下所示:
目前,我們已將Gatling與Gradle集成在一起,但是這里缺少一個(gè)片段,它在方程式上添加了連續(xù)部分。 為了添加連續(xù)的壓力測試,我們將使用Jenkins和Jenkins Pipeline作為CI服務(wù)器,因此對(duì)于每個(gè)提交都執(zhí)行壓力測試 ? 其他任務(wù),例如編譯,運(yùn)行單元,集成測試或代碼質(zhì)量門。
過去, Jenkins作業(yè)是使用Web UI配置的,需要用戶手動(dòng)創(chuàng)建作業(yè),填寫作業(yè)的詳細(xì)信息并通過Web瀏覽器創(chuàng)建管道。 同樣,這使得保持作業(yè)的配置與正在構(gòu)建的實(shí)際代碼分離。
隨著Jenkins Pipeline插件的引入。 該插件是Groovy DSL,可讓您在文件中實(shí)施整個(gè)構(gòu)建過程,并將其與代碼一起存儲(chǔ)。 Jenkins 2.0默認(rèn)帶有此插件,但是如果您使用的是Jenkins 1.X,則可以將其安裝為其他任何插件( https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+Plugin )
因此,現(xiàn)在我們可以開始對(duì)發(fā)布插件進(jìn)行編碼了,但是出于本文的目的,僅涉及壓力部分。 您需要在項(xiàng)目的根目錄上創(chuàng)建一個(gè)名為Jenkinsfile的文件(名稱不是強(qiáng)制性的,但實(shí)際上是名稱),在本例中為下一個(gè)內(nèi)容:
stage 'Compile And Unit Test'stage 'Code Quality'stage 'Integration Test'stage 'Acceptance Test'// defines an stage for info purposes stage 'Stress Test'def dockerHost = '...' //defines a node to run the stage node {// get source code from location where Jenkinsfile (this) is located.// you could use stash/unstash to get sources from previous stages instead of getting from SCMcheckout scm// defines the environment variable for stress testwithEnv(["starwars_planets_url=http://${dockerHost}:9090/starwars/"]) {// executes shell scriptsh './gradlew test'}}在這種情況下,我們定義了一個(gè)新階段,稱為壓力測試。 階段步驟僅用作參考,將用于記錄目的。 接下來定義一個(gè)節(jié)點(diǎn)。 節(jié)點(diǎn)是執(zhí)行代碼的Jenkins執(zhí)行程序。 在此節(jié)點(diǎn)內(nèi),從放置Jenkinsfile的同一位置檢出源代碼,設(shè)置一個(gè)新的環(huán)境變量以指出應(yīng)用程序的部署位置,最后是執(zhí)行Gradle測試任務(wù)的shell步驟。
Jenkins的最后一步是創(chuàng)建Pipeline類型的新作業(yè),并設(shè)置Jenkinsfile的位置。 因此,轉(zhuǎn)到“ 詹金斯”>“新項(xiàng)目”>“管道”,并為作業(yè)命名。
然后,您只需要轉(zhuǎn)到“ 管道”部分,并配置用于存儲(chǔ)項(xiàng)目的SCM存儲(chǔ)庫。
然后,如果您已經(jīng)正確配置了來自Jenkins和SCM服務(wù)器的掛鉤,那么將為每次提交執(zhí)行此作業(yè),因此您的壓力測試將連續(xù)運(yùn)行。
當(dāng)然,您可能已經(jīng)注意到壓力測試已執(zhí)行,但是Jenkins沒有發(fā)布任何報(bào)告,因此您無法查看或比較不同執(zhí)行的結(jié)果。 因此,您可以使用publishHtml插件將生成的報(bào)告存儲(chǔ)在Jenkins中 。 如果尚未安裝該插件,則需要與其他任何Jenkins插件一樣安裝。
PublishHtml插件使我們可以將構(gòu)建工具生成的一些html文件發(fā)布到Jenkins,以便用戶可以使用,也可以按內(nèi)部版本號(hào)進(jìn)行分類。 您需要配置要發(fā)布的文件目錄的位置,在這里我們找到了第一個(gè)問題,您還記得蓋特林生成帶有隨機(jī)數(shù)的目錄嗎? 因此,我們需要首先解決此問題。 您可以采用不同的策略,但是最簡單的方法是在測試后將目錄重命名為已知的靜態(tài)名稱。
打開Gradle構(gòu)建文件并添加下一個(gè)內(nèi)容。
task(renameGatlingDirectory) << {// find the directorydef report = {file -> file.isDirectory() && file.getName().startsWith('averageorbitalperiodsimulation')}def reportDirectory = new File("${buildDir}/reports/gatling-results").listFiles().toList().findAll(report).sort().last()// rename to a known directory// should always work because in CI it comes from a clean executionreportDirectory.renameTo("${buildDir}/reports/gatling-results/averageorbitalperiodsimulation") }// it is run after test phase test.finalizedBy renameGatlingDirectory我們正在創(chuàng)建一個(gè)在測試任務(wù)結(jié)束時(shí)執(zhí)行的新任務(wù),該任務(wù)將最后創(chuàng)建的目錄重命名為averageorbitalperiodsimulation 。
最后一步是在shell調(diào)用之后在Jenkinsfile下一個(gè)調(diào)用中添加:
publishHTML(target: [reportDir:'stress-test/build/reports/gatling-results/averageorbitalperiodsimulation', reportFiles: 'index.html', reportName: 'Gatling report', keepAll: true])之后,您可能會(huì)在作業(yè)頁面中看到一個(gè)指向報(bào)告的鏈接。
就是如此,多虧了Gradle和Jenkins,您可以輕松地實(shí)施持續(xù)的壓力測試策略,而只需使用所有開發(fā)人員都講的語言代碼即可。
我們不斷學(xué)習(xí),
亞歷克斯
翻譯自: https://www.javacodegeeks.com/2016/04/continuous-stress-testing-jax-rs-javaee-applications-gatling-gradle-jenkins-pipeline.html
gatling 使用
總結(jié)
以上是生活随笔為你收集整理的gatling 使用_使用Gatling + Gradle + Jenkins Pipeline为您的JAX-RS(和JavaEE)应用程序进行连续压力测试...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 停止新游戏备案什么意思(停止新游戏备案)
- 下一篇: java 交替_Java 8:使用交替接