性能测试工具 Gatling 学习笔记

xinxi · 2019年07月25日 · 最后由 bill 回复于 2020年04月05日 · 43 次阅读

前言

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")
  //设置baseurlheader    

  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

共收到 5 条回复 时间 点赞

总结的很全面不错👍

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

大神,请问 gatling 中 response 中提取了参数为 order_no,怎么作为第二个接口的入参使用

冰薄荷 回复

为什么最后回归 jmeter?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册