html开发的移动端怎么做压力测试,使用Gatling做web压力测试

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)

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值