性能测试工具 Gatling 学习笔记

xinxi · July 25, 2019 · Last by 笑哼 replied at July 26, 2019 · 1962 hits

前言

Gatling基于Scala开发的压测工具,我们可以通过录制自动生成脚本,也可以自己编写脚本.

熟悉jmeter的同学应该知道Jmeter基于jvm的多线程,一但请求连接数太大,性能就会急速下降.

Gatling使用是异步IO,并发性更强.基于jvm的Actors模型,用更少的内存和cpu.

Gatling并不完美,不支持分布书、支持的协议比较少、需要了解Scala语法.

本文并不会评判jmeter和Gatling的好坏,仅抱着学习的心态去了解Gatling.

环境搭建

官网:https://gatling.io

下载的是"gatling-charts-highcharts-bundle-3.2.0-bundle.zip"文件.

image

解压后,目录结构如下:

image

bin目录是可执行文件,在windows执行.bat文件,mac和
linux执行.sh文件.

image

conf是配置文件用的,其中gatling.conf中可以设置gatling相关配置,比如控制台输出、文件输出等

image

logback.xml是设置控制台输入log级别和时间戳等信息,类似log4j中的配置,如果本地调试话还是很有用的.

image

脚本录制

录制

gatling也提供了脚本录制功能,运行"recorder.sh"文件

录制分两种,一种是代理录制,另外一种是har文件,.har文件可以用charles导出成.har格式.

image

手机代理写上ip + 8000端口.点击开始,就可以拦截到接口数据.

image

录制完后成也会生成.scala文件

image

回放

在bin目录下,执行gatling.sh命令

输入选择的脚本序号和描述(两个回车就可以跳过了)

image

image

报告

压测报告是每次压测完后才会生成的.

生成的报告相比jmeter高大上了不少,接口耗时分布、状态饼图等.

image

image

编写脚本

gatling可以使用IDE工具(idea)编写脚本,使用maven管理需要的依赖和脚本.

在pom.xml中增加gatling-maven-plugin插件和scala-maven-plugin插件

image

第一个脚本

这是一个官网介绍的压测脚本,新建一个BasicSimulation类需要继承Simulation.

写接口路径、header头、并发用户数、持续压测时间等信息.

package computerdatabase 

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class BasicSimulation extends Simulation {

val httpProtocol = http
.baseUrl("http://computer-database.gatling.io")
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.doNotTrackHeader("1")
.acceptLanguageHeader("en-US,en;q=0.5")
.acceptEncodingHeader("gzip, deflate")
.userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0")
//设置baseurl和header头

val scn = scenario("BasicSimulation")
.exec(http("request_1")
.get("/")) // 设置path路径
.pause(5)
setUp(
scn.inject(atOnceUsers(1)) //设置并发用户数
).protocols(httpProtocol)
}

脚本串联

gatling比较好的一个功能,就是可以把业务串联起来.

比如:首页->详情->下单-支付.这个业务逻辑就是一个简单的全链路.

class BuySimulation extends Simulation {

val httpProtocol = http
.baseUrl("http://computer-database.gatling.io") // Here is the root for all relative URLs
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") // Here are the common headers
.acceptEncodingHeader("gzip, deflate")
.acceptLanguageHeader("en-US,en;q=0.5")
.userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0")

val scn = scenario("Scenario Name") // A scenario is a chain of requests and pauses
.exec(http("request_home")
.get("/home"))
.pause(7) // Note that Gatling has recorder real time pauses
.exec(http("request_detail")
.get("/ebookdetail?id=123"))
.pause(2)
.exec(http("request_buy") // Here's an example of a POST request
.post("/buy")
.formParam("""name""", """时间简史""")
)

setUp(scn.inject(atOnceUsers(1000)).protocols(httpProtocol))
}

这个脚本是从串联的三个接口并且在每个接口设置一定的停顿时间,总体是并发1000的虚拟用户.

这个场景也比较符合压测的漏斗效应,在最后面的接口一般都是用户请求量较小的(比如支付).

设置压测时间

一般压测都会持续10分钟以上,可以使用during(100)设置时间.

class TimeSimulation extends Simulation {

val httpProtocol = http
.baseUrl("http://www.baidu.com")
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.acceptEncodingHeader("gzip, deflate")
.acceptLanguageHeader("en-US,en;q=0.5")
.userAgentHeader("Mozilla/5.0")

val scn = scenario("BaiduSimulation").during(100){
exec(http("baidu_home").get("/"))
}
setUp(
scn.inject(
atOnceUsers(10),
).protocols(httpProtocol)
)
}

相关参数

在setUp中还可以设置额外参数来模拟真实场景.

nothingFor(4 seconds)  在指定的时间段(4 seconds)内什么都不干

atOnceUsers(10) 一次模拟的用户数量(10)

rampUsers(10) over(5 seconds) 在指定的时间段(5 seconds)内逐渐增加用户数到指定的数量(10)

constantUsersPerSec(10) during(20 seconds) 以固定的速度模拟用户,指定每秒模拟的用户数(10),指定模拟测试时间长度(20 seconds)

constantUsersPerSec(10) during(20 seconds) randomized 以固定的速度模拟用户,指定每秒模拟的用户数(10),指定模拟时间段(20 seconds)。用户数将在随机被随机模拟(毫秒级别

rampUsersPerSec(10) to (20) during(20 seconds) 在指定的时间(20 seconds)内,使每秒模拟的用户从数量1(10)逐渐增加到数量2(20),速度匀速

rampUsersPerSec(10) to (20) during(20 seconds) randomized 在指定的时间(20 seconds)内,使每秒模拟的用户从数量1(10)增加到数量2(20),速度随机

splitUsers(100) into(rampUsers(10) over(10 seconds)) separatedBy(10 seconds) 反复执行所定义的模拟步骤(rampUsers(10) over(10 seconds)),每次暂停指定的时间(10 seconds),直到总数达到指定的数量(100)

splitUsers(100) into(rampUsers(10) over(10 seconds)) separatedBy(atOnceUsers(30)) 反复依次执行所定义的模拟步骤1(rampUsers(10) over(10 seconds))和模拟步骤2(atOnceUsers(30)),直到总数达到指定的数量(100)左右

heavisideUsers(100) over(10 seconds) 在指定的时间(10 seconds)内使用类似单位阶跃函数的方法逐渐增加模拟并发的用户,直到总数达到指定的数量(100).简单说就是每秒并发用户数递增

分布式

gatling不支持分布式,就意味着不能像jmeter那样,由master机器控制多个slave一起工作.

但是实际压测的时候肯定还是需要多个机器同一时间压测才能达到高并发.

这里只能曲线救国一把,结合jenkins的pipeline脚本控制多个节点并发.

脚本中使用了两台jenkins节点机器,通过agent的标签指定节点.

脚本可以提前上传到服务器上,或者放到github上每次运行的时候拉下来.

pipline中使用parallel才可以达到节点并发执行.

pipeline {
agent none

stages {
stage('run tests') {
parallel {
stage('aliyun_agent') {
agent {
label 'aliyun'
}
steps {
sh 'pwd'
sh 'cd ~/jenkins_node/workspace/pipline_gatling_test/gatling-maven-plugin-demo && mvn gatling:test'
}
}

stage('jingdong_agent') {
agent {
label 'jingdong'
}
steps {
sh 'pwd'
sh 'cd /root/doc/gatling-docker/gatling-maven-plugin-demo && mvn gatling:test'
}
}
}
}
}
}

可视化展示

gatling的报告也是每次运行完成后才会生成,不能实时查看当前压测QPS及RT时间.

jmeter方案

在jmeter方案中,如果想实时查看压测qps及rt时间,是在脚本中配置后端监听器并且配置influxdb地址,jmeter会把压测过程中数据实时传给influxdb存储,前端配合grafana展示就可以完成实时展示了.

gatling方案

在gatling方案中也是类似的思路,但是不知道怎么把压测试试传到influxdb上.

后来想到了gatling有个gatling.conf文件,其中有段配置如下:

image

这段配置是的意思是可以把数据写到graphite的host + 2003地址上.

grafana && influxdb

这里使用docker-compose启动两个镜像,配置如下:

在influxdb的中influxdb.conf配置graphite.

image

influxdb开启了三个端口,其实2003就是刚才gatling.conf配置中.

image

展示效果

image

项目地址

https://github.com/xinxi1990/gatling-docker-test.git

结语

目前市面上的Gatling学习资料比较少,建议还是看官网.

如果大家有一定压测经验或者已经掌握了Jmeter,学习起来比较好入门.

参考

https://blog.csdn.net/smooth00/article/details/80014622

https://github.com/gatling/gatling-maven-plugin-demo

共收到 3 条回复 时间 点赞

总结的很全面不错👍

研究过一段时间Gatling,最后还是回归了jmeter

膜拜

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up