Gatling是什么
Gatling是一个使用Scala编写的开源的负载测试框架,基于Akka和Netty,具有以下亮点:
· 高性能
· 友好的HTML报告
· 基于情境的记录器(recoder),对开发友好的DSL
Gatling VS Jmeter
Jmeter是目前非常成熟的负载测试工具,支持相当多的协议,支持插件,可以轻松的扩展。
而Gatling性能上更有优势,并且使用Scala DSL代替xml做配置,相比jmeter要更灵活,而且更容易修改和维护。
关于Jmeter和Gatling的一个比较好的对比可以参见 infoq的文章
同时,Gatling也对 Maven 和 Gradle 这样的构建工具比较友好,易于集成到 Jenkins 中,轻松加入到CI流程中。
TIPS: 在实际使用中建议版本化管理gatling的配置,使用 maven插件 或 gradle插件 形成对应的maven/gradle工程项目管理,更容易,而且容量更小,升级gatling也会更方便,减少了很多手工的操作。
Gatling的基本使用
从官方网站 下载 zip压缩包,解压就行了,需要预先安装有JDK,并设置好 JAVA_HOME ,熟悉JAVA的朋友应该都懂,就不细说了。
Gatling的目录结构看起来像这样:
│ LICENSE
│
├─bin
│ gatling.bat
│ gatling.sh
│ recorder.bat
│ recorder.sh
│
├─conf
│ gatling-akka.conf
│ gatling.conf
│ logback.xml
│ recorder.conf
│
├─lib
├─results
│ .keep
│
└─user-files
├─bodies
│ .keep
│
├─data
│ search.csv
│
└─simulations
└─computerdatabase
│ BasicSimulation.scala
│
└─advanced
AdvancedSimulationStep01.scala
AdvancedSimulationStep02.scala
AdvancedSimulationStep03.scala
AdvancedSimulationStep04.scala
AdvancedSimulationStep05.scala
bin/ 目录存放gatling的可执行文件, conf/ 存放配置,通常保持默认即可, lib/ 存放gatling本身的依赖,用户不用管, results/ 存放报告, user-files/ 是用户最主要使用的目录,用户定义的测试场景相关的代码均存放于此目录下。
zip包解压缩以后已经带有了一个官方的示例文件 BasicSimulation.scala ,想看看演示效果的直接使用 bin/gatling.(bat|sh) 启动就可以了。这个演示的场景描述见 官方文档 。那几个 AdvancedSimulationStep 其实效果上和 BasicSimulation 完全一致,只是官方提供了一些参考的DSL写法而已。
一些实战中的DSL参考范例
尽管gatling和jmeter一样,带有一个图形化的recorder,但是功能极其简陋,只能模拟一个用户,并且没有结构化代码架构。因此只能用来生成最基本的框架,绝大多数情况需要用户自己编写DSL,其实官方文档中几乎已经涵盖了大部分的用例,照着抄就可以了。这里提供几个参考的DSL
Random不起作用?
有时候我们需要在测试场景中引入随机数,从而更好的模拟大量用户请求的场景。很自然的想到几乎各个编程语言都带有 Random 函数库。而Scala自然也不例外,带有一个
scala.util.Random 类库。但是实际使用的时候可能会发现没用。比如下面这个例子:
forever(
exec(http("Random id browse")
.get("/articles/" + scala.util.Random.nextInt(100))
.check(status.is(200))
)
这个 scala.util.Random.nextInt(100) 会发现只有第一次会随机生成一个数字,后面都不变。按照gatling的官方文档的解释,由于DSL会预编译,在整个执行过程中是静态的。因此Random在运行过程中就已经静态化了,不会再执行。应改为 Feeder 实现。 Feeder 是gatling用于实现注入动态参数或变量的。改用 Feeder 实现:
val randomIdFeeder =
Iterator.continually(Map("id" ->
(scala.util.Random.nextInt(100))))
forever(
feed(randomIdFeeder)
.exec(http("Random id browse")
.get("/articles/${id}"))
.check(status.is(200))
)
feed() 在每次执行时都会从 Iterator[Map[String, T]] 对象中取出一个值,这样才能实现这个需求。
使用 import 引入外部方法
例如专门写一个 Feeders.scala 文件,存储着各种需要用到的 Feeder :
import scala.util.Random
object LinchangFeeders {
def randomGeoFeeder() : Iterator[Map[String, Number]] = {
val LNG_RANGE = List(108.75, 109.1)
val LAT_RANGE = List(34.0, 34.4)
return Iterator.continually(
Map(
"lng" -> (
Random.nextFloat() * (LNG_RANGE(1)
- LNG_RANGE(0)) + LNG_RANGE(0)
)
,"lat" -> (
Random.nextFloat() * (LAT_RANGE(1)
- LAT_RANGE(0)) + LAT_RANGE(0)
)
)
)
}
def randomOffsetFeeder() : Iterator[Map[String, Number]] = {
Iterator.continually(Map("offset" -> Random.nextInt(100)))
}
}
然后在 MySimulation.scala 就可以 import ,使用里面定义好的方法了:
import scala.concurrent.duration._
import scala.util.Random
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
import Feeders._
class MySimulation extends Simulation {
val brownse = feed(randomOffsetFeeder)
.exec(
home
)
}
用户注入策略
<= 10: 一把注入
> 10: 每10秒注入10个用户
val injectStrategy =
if (USERS_COUNT > 10) {
splitUsers(USERS_COUNT) into(
rampUsers(10) over(5 seconds)
) separatedBy(10 seconds)
} else {
atOnceUsers(USERS_COUNT)
}
压测时间策略
= 0: 所有模拟用户不循环,执行完测试场景即退出
> 0: 所有模拟用户循环执行测试场景,直到达到指定时间
val scn = scenario("My test scenario")
.doIfOrElse(DURATION > 0) {
forever(
exec(steps)
)
} {
exec(steps)
}
val setup = setUp(
scn.inject(
injectStrategy
).protocols(httpProtocol)
)
if (DURATION > 0) {
setup.maxDuration(DURATION minutes)
}
使用Gatling做Web压力测试
发表于:2017-02-07
作者:SegmentFault
来源:
 相关文章
软件测试:测试一个网站 软件测试之全网最全Web端测试点 软件测试之Web自动化测试怎么做?Web... 怎样正确做 Web 应用的压力测试? 0代码就可以实现网页签到测试 如何对网站和应用程序进行本地化测试?- 周排行
- 月排行
-   Cookie测试:如何在web上测试Cookie
-   软件测试:网站登录不进去,该如何排...
-   Web功能测试常用方法
-   优化网站性能架构提升用户体验(下)
-   7天自动登录网站怎么测
-   Web功能测试总结
-   跨浏览器网页效果免费自动测试网站分享
-   一次完整的安全渗透测试
-   Cookie测试:如何在web上测试Cookie
-   软件测试之全网最全Web端测试点
-   大型网站压力测试及优化方案
-   怎样正确做 Web 应用的压力测试?