一篇入门 — Gatling 性能测试手册

介绍

本篇博客,旨在记录学习的要点,因此格式随意, 方便本人往后自考和回忆,有兴趣的朋友能够评论讨论。
原文地址:https://www.cnblogs.com/clockq/p/10539974.htmljavascript

一. 性能测试基础

1.1 性能测试时什么?

==性能测试时经过自动化的测试工具模拟多种正常峰值、以及异常负载条件,以此来对系统的各项性能指标进行评测。==css

性能测试 = 负载测试 + 压力测试html

  1. 经过负载测试,肯定在各类工做负载下系统的性能,目的是测试系统的负载逐渐增长的状况下,系统的各项性能指标的变化状况。
  2. 经过压力测试,肯定一个系统的瓶颈或者不能接受的性能点,来得到系统所能提供的最大服务级别。

1.2 ==性能测试的目的==

  1. 评估系统的能力
  2. 识别体系中的弱点
  3. 系统调优
  4. 检查软件中的问题
  5. 验证系统稳定性
  6. 验证系统可靠性

1.3 性能测试的常见观察指标

  • Avg Rps: 平均每秒响应次数 = 总请求时间 / 秒数
  • Avg time to last byte per terstion(mstes): 平均每秒业务脚本迭代次数
  • Successful Rounds: 成功的请求
  • Failed Hits: 失败的单击次数
  • Hits Per Second: 每秒单击次数
  • Successful Hits Per Second: 每秒成功的单击次数
  • Failed Hist Per Second: 每秒失败的单击次数
  • Attempted Connections: 尝试链接数
  • Throughput: 吞吐率

同时,对于服务端的CPU占有率,内存占有率,数据库链接池等也是须要观察的重点。前端

1.4 性能测试的基本流程

  1. 明确性能测试需求
  2. 制定性能测试方案
  3. 编写性能测试案例
  4. 执行性能测试案例
  5. 分析性能测试结果
  6. 生成性能测试报告

二. Gatling基础 -> 基础使用法

2.1 安装Gatling

获取安装包 http://gatling.io.download/
下载成功后解压便可 使用Gatling须要安装JDKjava

2.2 使用Gatling

  1. 编写测试脚本(这块重点学习和讲解)或者使用自带的录制器(bin/recorder.sh)
  2. 执行测试脚本(bin/gatling.sh),在开启的窗口中选择要执行的脚本
  3. 查看测试报告(报告默认在“result/”目录下)
  4. 分析测试结果

三. Gatling 和 Mvn 整合使用 (推荐)

3.1 导入依赖

<properties>
        <gatling.version>2.1.7</gatling.version>
        <gatling-plugin.version>2.1.7</gatling-plugin.version>
    </properties>
    
    <!-- Gatling Module -->
    <dependency>
        <groupId>io.gatling.highcharts</groupId>
        <artifactId>gatling-charts-highcharts</artifactId>
        <version>${gatling.version}</version>
    </dependency>

3.2 导入插件

<build>
    <sourceDirectory>src/test/scala</sourceDirectory>
    <testSourceDirectory>src/test/scala</testSourceDirectory>
    <plugins>
        <!-- Gatling Maven plugin that runs the load-simulation. -->
        <plugin>
            <groupId>io.gatling</groupId>
            <artifactId>gatling-maven-plugin</artifactId>
            <version>${gatling-plugin.version}</version>
            <configuration>
                <configFolder>src/test/resources</configFolder>
                <dataFolder>src/test/resources/data</dataFolder>
                <resultsFolder>target/gatling/results</resultsFolder>
                <runMultipleSimulations>true</runMultipleSimulations>
                <simulationsFolder>src/test/scala/com/pharbers/gatling</simulationsFolder>

                <simulationClass>com.pharbers.gatling.scenario.getHome</simulationClass>

                <!--    <noReports>false</noReports> -->
                <!--   <reportsOnly>directoryName</reportsOnly> -->
                <!--   <simulationClass>foo.Bar</simulationClass> -->
                <!--   <jvmArgs> -->
                <!--     <jvmArg>-DmyExtraParam=foo</jvmArg> -->
                <!--   </jvmArgs> -->
                <!--    <fork>true</fork> -->
                <!--    <propagateSystemProperties>true</propagateSystemProperties> -->
                <!--   <failOnError>true</failOnError> -->
            </configuration>
        </plugin>
    </plugins>
</build>

3.3 编写脚本

忽略
注意: 脚本要写在 src/test/scala 下web

3.4 执行脚本

mvn gatling:execute数据库

3.5 分析报告

四. 现实测试举例

咱们先以测试“博客园系统登陆页”性能为例,讲解一次测试过程的几个步骤,和测试报告怎么分析。json

4.1 明确性能测试需求

好的开始是成功的一半api

明确性能测试的需求是相当重要的,因此咱们要先有一份测试需求实例服务器

测试需求名称: 博客园登陆接口性能测试 | 信息描述 | 描述内容 | | :--: | :--: | | 参与者 | 张三 | | 概述 | 测试博客园登陆接口的最大并发量 | | 前置条件 | 博客园前端页面已经成功部署,并能够正常访问 | | 后置条件 | 无 | | 业务数据 | 测试登陆帐号 | | 不可测试缘由 | 网络不可达 | | 流程规则 | 用户访问博客园登陆页,滞留5s,以后调用登陆接口 | | 业务规则 | 无 | | 页面规则 | 无 | | 特殊规则 | 无 | | 接口规则 | 无 | | 检查内容 | 检查当用户量达到多大时,会致使服务端阻塞,用户响应时间超过5s |

4.2 编写性能测试案例

测试需求名称: 博客园登陆接口性能测试 | 测试步骤 | 步骤描述 | 预期结果 | | :--: | :--: | :--: | | 步骤 1 | 是否测试博客园登陆接口最大并发量 | 肯定性能测试登陆接口的并发用户数量 | | 步骤 2 | 启动博客园的前端工程 | 前端工程启动成功 | | 步骤 3 | 准备性能测试脚本 | 性能测试脚本准备完成 | | 步骤 4 | 准备测试数据 | 无 | | 步骤 5 | 执行脚本,验证系统是否知足相关性能测试指标 平均响应时长<2s 95%响应时长<= 5s | 系统知足相关性能测试指标 | | 步骤 5 | 执行1小时压力测试 | 1. 系统知足相关性能测试指标 2. 1小时压力测试中脚本未报错 |

4.3 执行性能测试案例

按照性能测试案例编写测试脚本

package com.pharbers.gatling.base

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.http.config.HttpProtocolBuilder

object phHttpProtocol {
    implicit val noneWhiteList: io.gatling.core.filter.WhiteList = WhiteList()
    implicit val noneBlackList: io.gatling.core.filter.BlackList = BlackList()
    implicit val staticBlackList: io.gatling.core.filter.BlackList = BlackList(""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.(t|o)tf""", """.*\.png""")
    implicit val staticWhiteList: io.gatling.core.filter.WhiteList = WhiteList(""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.(t|o)tf""", """.*\.png""")

    def apply(host: String)
             (implicit blackLst: io.gatling.core.filter.BlackList, whiteLst: io.gatling.core.filter.WhiteList): HttpProtocolBuilder = { http
                .baseURL(host)
                .inferHtmlResources(blackLst, whiteLst)
                .acceptHeader("application/json, text/javascript, */*; q=0.01")
                .acceptEncodingHeader("gzip, deflate")
                .acceptLanguageHeader("zh-CN,zh;q=0.9,zh-TW;q=0.8")
                .doNotTrackHeader("1")
                .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")
    }
}
package com.pharbers.gatling.base

object phHeaders {

    val headers_base = Map(
        "Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "Upgrade-Insecure-Requests" -> "1")
}
package com.pharbers.gatling.scenario

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.core.structure.ChainBuilder

import com.pharbers.gatling.base.phHeaders.headers_base

object getHome {
	val getHome: ChainBuilder = exec(http("home")
			.get("/")
			.headers(headers_base))
}
package com.pharbers.gatling.scenario

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.core.structure.ChainBuilder

import com.pharbers.gatling.base.phHeaders.headers_json

object userLogin {
	val feeder = csv("loginUser.csv").random
	println(feeder)

	val login: ChainBuilder = exec(http("login")
			.get("/api/user/login")
			.headers(headers_json)
			.body(StringBody("""{ "condition" :  { "email" : "nhwa", "password" : "nhwa" } }""")).asJSON)
}
package com.pharbers.gatling.simulation

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

import com.pharbers.gatling.scenario._
import com.pharbers.gatling.base.phHttpProtocol

class userLogin extends Simulation {
	import com.pharbers.gatling.base.phHttpProtocol.{noneBlackList, noneWhiteList}

	val httpProtocol = phHttpProtocol("http://192.168.100.141:9000")

	val scn = scenario("user_login")
		.exec(
			getHome.getHome
					.pause(5 seconds),
			userLogin.login
					.pause(60 seconds)
		)

	setUp(scn.inject(rampUsers(1000) over (3 seconds))).protocols(httpProtocol)

}

并执行上述脚本

4.4 分析性能测试结果

看下图,能够看到67% + 8%的请求能够在1.2s内彻底,同时在1000用户的并发测试下,会有用户请求不到资源,也就是加载失败。

其实,这个地方,能够经过修改gatling.conf来改变表格的渲染区间,使结果更符合咱们的测试要求

image

这里,75th的总响应时间=1s,仍是很快的,但95th的总响应时间>9s, 因此不符合咱们的测试要求。 image

咱们使用递增的方式,在3s内逐渐增长用户并发量,而且用户会滞留5s + 60s,在下图中就获得了体现 image

下图是本次测试,在每一个时间点的请求状况,包含请求状态(成功,失败)和请求数量 image

还有更多图表,就不一一展现了,咱们主要就是查看前两个图表,以此判断服务器所能承受的压力。

固然,若是须要考查更多标准,就须要查看其它图表,好比延迟分布图,负载分布图等等。。。。

4.5 生成性能测试报告

一份合格的性能测试报告,至少应该包含以下内容:

  1. 测试基本信息: 包含: 测试目的,报告目标读者,术语定义,参考资料
  2. 测试环境描述: 包含: 服务器软硬件环境,网络环境,测试工具,测试人员
  3. 性能测试案例执行分析: 须要详细描述每一个测试案例的执行状况,以及对对应测试结果进行分析
  4. 测试结果综合分析及建议:对本次性能测试作综合分析,并给出测试结论和改进建议
  5. 测试经验总结

博客园登陆接口性能测试报告

测试信息

信息描述 描述内容
测试人员 齐钟昱
测试目的 检查当用户量达到多大时,会致使服务端阻塞,用户响应时间超过5s
术语定义 50th,安装递增排序后,排在50%的请求的信息
术语定义 95th,安装递增排序后,排在95%的请求的信息
参考资料 零成本实现Web性能测试[电子工业出版社]

测试环境

信息描述 描述内容
服务器系统 CentOS Linux release 7.4.1708 (Core)
服务器集群数量 4
服务器内存(台) 16G
服务器CPU核心数(台) 12
服务器硬盘空间(台) 256G SSD
JAVA版本 1.8.121
Scala版本 2.11.8
Play版本 2.5.0-M2
Redis版本 4.0.1
MongoDB版本 3.4.4
Node.js 8.11.2
Ember.js 2.18.2
网络环境 公司局域网
测试工具 Gatling 2.1.7

结果分析

测试内容 预期结果 测试结果 备注
博客园系统登陆页的最大访问量 在当前环境下能够1000用户并发,不会形成用户请求失败 在3s内逐渐提升并发量,当并发量在643时有三个资源请求失败,在并发量达到689时,有64个资源请求失败 未经过,当前博客园系统登陆页的最大访问量应小于643
博客园系统登陆接口的最大并发量 在当前环境下能够1000用户并发,不会形成用户请求失败 在3s内逐渐提升并发量,当并发量达到1000时,请求资源仍所有成功 经过
博客园登陆页的响应时间 在当前环境下用户平均响应时长<2s 95%响应时长<= 5s 50th响应时间为1.6s,95th为22s 未经过
博客园登陆接口的响应时间 在当前环境下用户平均响应时长<2s 95%响应时长<= 5s 50th响应时间 < 1s,95th < 1s 经过

测试总结

根据上述分析报告,本次性能测试为经过制定要求,博客园系统登陆功能的最大并发量应小于643,为保持性能,建议并发数小于500

五. 经常使用脚本api

5.1 并发量控制

  1. atOnceUsers(100) 使用100并发量测试目标服务器
  2. rampUsers(100) over (10 seconds) 按部就班的增大压力,在10s中内线性增长用户数达到最大压力100并发量
  3. nothingFor(10 seconds) 等待10s
  4. constantUsersPerSec(rate) during(duration) 在指定duration内,以固定频率注入用户,每秒注入rate个用户,默认固定间隔
  5. constantUsersPerSec(rate) during(duration) randomized 与上面不一样的是用户以随机间隔注入
  6. rampUsersPerSec(rate1) to (rate2) during(duration) 在指定duration内,以递增频率注入用户,每秒注入 rate1 ~ rate2 个用户

5.2 用户行为控制

  1. .exec() 实际的用户行为
  2. .pause(20) 用户滞留20s,模拟用户思考或者浏览内容
  3. .pause(min: Duration, max: Duration) 用户随机滞留,滞留时间在min ~ max 之间

5.3 流程控制

  1. repeat(time, counterName) 内置循环器
  2. foreach(seq, elem, counterName) foreach循环器
  3. csv("file").random 建立填充器
  4. doIf("", "") 判断语句
相关文章
相关标签/搜索