介绍

本篇博客,旨在记录学习的要点,所以格式随意, 方便本人日后自考和回忆,有兴趣的朋友可以评论讨论。

原文地址:https://www.cnblogs.com/clockq/p/10539974.html

一. 性能测试基础

1.1 性能测试时什么?

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

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

  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需要安装JDK

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 下

3.4 执行脚本

mvn gatling:execute

3.5 分析报告

四. 现实测试举例

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

4.1 明确性能测试需求

好的开始是成功的一半

明确性能测试的需求是至关重要的,所以我们要先有一份测试需求实例

测试需求名称: 博客园登录接口性能测试

信息描述 描述内容
参与者 张三
概述 测试博客园登录接口的最大并发量
前置条件 博客园前端页面已经成功部署,并可以正常访问
后置条件
业务数据 测试登录账号
不可测试原因 网络不可达
流程规则 用户访问博客园登录页,滞留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来改变表格的渲染区间,使结果更符合我们的测试要求

这里,75th的总响应时间=1s,还是很快的,但95th的总响应时间>9s, 所以不符合我们的测试要求。

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

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

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

当然,如果需要考查更多标准,就需要查看其它图表,比如延迟分布图,负载分布图等等。。。。

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("", "") 判断语句

一篇入门 — Gatling 性能测试手册的更多相关文章

  1. Tp5安全篇入门

    输入安全 设置public目录为唯一对外访问目录,不能把资源文件放入到应用目录: 使用框架提供的请求变量获取方法(Request类的param方法及input助手函数)而不是原生系统变量获取用户输入的 ...

  2. 测者的性能测试手册:JVM的监控利器

    测者的性能测试手册:JVM的监控利器 每次聊起性能测试,最后的终结话题就是怎么做优化.其实在Java的复杂项目中都会有内存不足问题.内存泄露问题.线程死锁问题.CPU问题.这些问题工程测试或者是小压力 ...

  3. 第一篇 入门必备 (Android学习笔记)

    第一篇 入门必备 第1章 初识Android 第2章 搭建你的开发环境 第3章 创建第一个程序--HelloWorld 第4章 使用Android工具   ●Android之父 Android安迪·罗 ...

  4. 一篇入门Express

    目录 1.安装 2.Hello World 3.基础路由设置 4.高级路由设置 5.静态文件 6.中间件 7.生成器 1.安装 Express 是一个 基于 Node.js 的简洁灵活的 Web 应用 ...

  5. 学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳

    学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 9 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第一篇) 入门详解 - 精简归纳 ...

  6. 学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳

    学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第二篇) 入门详解 - 精简归纳 ...

  7. 学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳

    学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 10 / 25 转载请注明出处!️ 目录 学会Git玩转GitHub(第三篇) 入门详解 - 精简归纳 ...

  8. jenkins:应用篇(Gatling plugin的使用)

    Jenkins的功能强大,在于它的插件式框架,能扩展功能,自动化当中,很容易想到的是对提交的新代码做测试,这里gatling主要是负责压力测试,也就是所谓的性能.关于gatling,可以参考我前面的博 ...

  9. 一篇入门 -- Scala

    整体介绍 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性. 联邦理工学院洛桑(EPFL)的Martin Odersky于2001 ...

随机推荐

  1. 关于Mybatis浅谈

    1. 历史 MyBatis本是apache的一个开源项目iBatis. 2010年这个项目由apache software foundation 迁移到了google code,并且取名为MyBati ...

  2. Zookeeper使用--命令行

    一.前言 在学习了Zookeeper相关的理论知识后,下面接着学习对Zookeeper的相关操作. 二.Zookeeper部署 Zookeeper的部署相对来说还是比较简单. Zookeeper有三种 ...

  3. jango路由层

    简单的路由配置: urls.py from django.contrib import admin from django.urls import path, re_path from book_ap ...

  4. Python内置的服务器的使用

    cd 到某一文件 Python内置的服务器: E:\myObject\office\netObject\new-gcms> python -m SimpleHTTPServer 8888 如果是 ...

  5. Springmvc中@RequestMapping 属性用法归纳

    简介: @RequestMapping RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上.用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径. RequestM ...

  6. 用SAX解析xml文件,java

    (此文为(https://www.imooc.com/video/4482)之随笔) 1.用SAX解析xml文件大致分为三步 写了一个XML文件作为例子 (1)main方法代码如下: import j ...

  7. Python中的迭代器、生成器

    from collections import Iterable, Iterator 1. 可迭代(iterable)对象 参考官网链接 class I: def __init__(self, v): ...

  8. linu输出重定向

    1.tee命令 ls | tee filename #若出现Permission Denied使用下面 ls | sudo tee filename #清空filename后重写 ls | sudo ...

  9. Swagger2基本注解使用

    @Api:用在请求的类上,表示对类的说明 tags="说明该类的作用,可以在UI界面上看到的注解" value="该参数没什么意义,在UI界面上也看到,所以不需要配置&q ...

  10. DAO和service的解释

    转自:http://blog.sina.com.cn/s/blog_4b1452dd0102wvox.html 我们都知道有了Hibernate后,单独对数据的POJO封装以及XML文件要耗损掉一个类 ...