性能测试工具: 企业中主流性能测试工具: jmeter
jmeter: java开发的开源,线程、学习很低,接口、自动化、性能测试、第三方性能测试从jmeter扩展
loadrunner: 商业 loadrunner(录播), 要付费购买并发用户数,脚本是c语言,性能比较好,性能指标值比较准确,性能测试的标杆
wrk: 快速响应性能测试工具,但是,不能做很复杂事情
ab: 快速响应性能测试工具,但是,不能做很复杂事情
ngrinder: 做性能侧开平台、性能工程的平台(groovy、jython)单节点可支持5000+并发(多进程,多线程)、支持分布式、可监控被测服务器、可录制脚本、开源、平台化
python + locust: python语言进行性能测试
一、wrk工具详解:
# 全空系统,初始化安装的一些软件
yum install git vim gcc wget unzip -y
# 使用git下载wrk的源码
git clone https://gitee.com/mirrors/wrk.git
# 安装make 防止系统没有make这个命令
yum install make -y
cd wrk
make
# 验证 wrk是否安装成功
./wrk -v
[root@centos7 wrk]# ./wrk -t4 -c100 -d60s --latency https://www.baidu.com/
Running 1m test @ https://www.baidu.com/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 330.39ms 165.67ms 1.87s 85.44%
Req/Sec 77.72 34.75 200.00 66.05%
Latency Distribution
50% 270.19ms
75% 353.73ms
90% 562.05ms
99% 944.58ms
18472 requests in 1.00m, 276.92MB read
Socket errors: connect 0, read 4, write 0, timeout 5
Requests/sec: 307.47
Transfer/sec: 4.61MB
二、Apache ab 工具详解:
php语言项目,apache中自动了这个工具
centos、Ubuntu中安装的工具名不一样
# centos
[root@centos7 wrk]# yum install httpd-tools -y
# ubuntu
apt-get -y install apache2-utils
Apache ab常见的参数:
-n 请求总数
-c 并发数
-r 连接异常时不要退出测试
-T content-type类型
-p 存放post请求参数的文件路径,发送post请求需要和 -T参数一起使用
-t 请求最大等待时间
ab的命令参数比较多,我们经常使用的是-c和-n参数。
我们现在就来测试apache的性能。使用如下命令:
$ ab -n 100 -c 10 http://13.209.21.196:8080/trade-server/test/order/testQueue
-n 100表示请求总数为100
-c 10表示并发用户数为10
http://13.209.21.196:8080/trade-server/test/order/testQueue表示请求的目标URL
这行表示处理100个请求并每次同时运行10次请求。
三、ngrinder工具详解:
ngrinder-controller 管理(管理界面、管理配置)
测试脚本: 自动生成、 + 手动修改(groovy 、jython)
groovy: java的衍生语言(有python基础的同学,去学习)
jython: java+ python ===python的脚本丢jvm虚拟机中运行
ngrinder-agent 代理, 压力机
目标机器====被测项目
ngrinder 性能测试开平台的优先选择
ngrinder 部署
依赖java运行环境, jre、jdk
ngrinder的版本,选择使用3.x版本,不要使用低于3的版本
ngrinder 3.x版本,jdk必须是1.8及以上,不能低于1.8
下载的包是war包
首先想到 tomcat
速度比较慢, 大概要2分钟左右,才能启动正常
ngrinder-controller使用微服务框架spring-boot开发,java -jar ngrinder-controller-3.5.2.war ----推荐
默认端口: 8080
http://ngrinder_ip:8080/ admin admin 语言可以选择中文
创建脚本
菜单栏 脚本 》 创建脚本
脚本名称: 选择语言: groovy、jython 、groovy maven project, 别名
选择请求方法,填写URL地址
高级选项: Content-Type: application/json 请求体
配置ngrinder-agent
web管理的登录名, 下载代理 这种方法下载的代理agent的配置文件,已经修改,不需要再次修改
如果不是这种方法下载,那么就要修改 agent.conf配置文件中controller的ip地址
解压包 tar -xvf ngrinder-agent-xxxxx.tar
agent部署在非被测服务器上
启动
# sh 结尾的linux文件
./run_agent.sh # 交互模式运行
./run_agent_bg.sh # 后台运行
./run_agent_internal.sh # 第一次是初始化运行
Controller
1. 分发调度测试任务
2.协调测试进程
3. 整理和显示测试的统计结果
4. 用户创建和修改脚本
Monitor
1.用于监控被测服务器的系统性能(例如:CPU/MEMORY)
2.必须部署在被测服务器上
Agent
1.压测任务的拉取
2.在代理服务器上加载运行测试进程和线程
3. 监控施压机器的系统性能(例如:CPU/MEMORY/网卡/磁盘)
非集群架构图
集群架构
nGrinder 从 3.1 版本开始支持 controller集群
由一个控制端controller和多个代理端agent组成,通过控制端(浏览器访问)建立测试场景,然后分发到代理端进行压力测试。
用户按照一定规范编写测试脚本,controller会将脚本以及需要的资源分发到agent,用jython、groovy执行。
在脚本执行的过程中收集运行情况、相应时间、测试目标服务器的运行情况等。并且保存这些数据生成测试报告,通过动态图和数据表的形式展示出来。用户可以方便的看到TPS、被测服务器的CPU和内存等情况。
选择最新的war包。
下载nGrinder
选择最新的war包。
服务器端启动: # nohup java -XX:MaxPermSize-256m -jar ngrinder-controller-3.5.2.war --port 8080 >output 2>&1 &
这样nGrinder的管理页面就部署好,你可以简单的把ngrinder-controller的功能理解为性能测试展示和控制,后面会进行详细介绍。
打开网址:
http://xxx.xxx.xxx.xxx:8080/login
默认用户名和密码都为admin
下载和agent
下载agent tar包(进入主页,点击 admin →Download Agent),然后进行解压 tar -xvf ngrinder-agent-3.5.2.tar
解压agent 后,目录结构如下,编辑进入__agent.conf
四、Groovy语言的简介
1.什么是groovy?
Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy 可以使用其他 Java 语言编写的库。
Groovy是一种基于Java平台的面向对象语言。 Groovy 1.0于2007年1月2日发布,其中Groovy 2.4是当前的主要版本。 Groovy通过Apache License v 2.0发布。
目前最新版本为2.5.3。
2.Groovy的特点
Groovy中有以下特点:
同时支持静态和动态类型
支持运算符重载
本地语法列表和关联数组
对正则表达式的本地支持
各种标记语言,如XML和HTML原生支持
Groovy对于Java开发人员来说很简单,因为Java和Groovy的语法非常相似
您可以使用现有的Java库
Groovy扩展了java.lang.Object
动态类型
类型对于变量,属性,方法,闭包的参数以及方法的返回类型都是可有可无的,都是在给变量赋值的时候才决定它的类型, 不同的类型会在后面用到,任何类型都可以被使用,即使是基本类型 (通过自动包装(autoboxing)). 当需要时,很多类型之间的转换都会自动发生,比如在这些类型之间的转换: 字符串(String),基本类型(如int) 和类型的包装类 (如Integer)之间,可以把不同的基本类型添加到同一数组(collections)中。
运算符重载
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
3.类
Groovy类和java类一样,完全可以用标准java bean的语法定义一个Groovy类。但作为另一种语言,可以使用更Groovy的方式定义类,这样的好处是,可以少写一半以上的javabean代码。
(1)不需public修饰符
如前面所言,Groovy的默认访问修饰符就是public,如果Groovy类成员需要public修饰,则根本不用写它。
(2)不需要类型说明
同样前面也说过,Groovy也不关心变量和方法参数的具体类型。
(3)不需要getter/setter方法
在很多ide(如eclipse)早就可以为程序员自动产生getter/setter方法了,在Groovy中,不需要getter/setter方法--所有类成员(如果是默认的public)根本不用通过getter/setter方法引用它们(当然,如果一定要通过getter/setter方法访问成员属性,Groovy也提供了它们)。
(4)不需要构造函数
不再需要程序员声明任何构造函数,因为实际上只需要两个构造函数(1个不带参数的默认构造函数,1个只带一个map参数的构造函数--由于是map类型,通过这个参数可以构造对象时任意初始化它的成员变量)。
(5)不需要;结尾
Groovy中每一行代码不需要分号作为结束符。
import HTTPClient.HTTPResponse import HTTPClient.NVPair import net.grinder.plugin.http.HTTPPluginControl import net.grinder.plugin.http.HTTPRequest import net.grinder.script.GTest import net.grinder.scriptengine.groovy.junit.GrinderRunner import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread import org.junit.Test import org.junit.runner.RunWith import static net.grinder.script.Grinder.grinder import static org.hamcrest.Matchers.is import static org.junit.Assert.assertThat // 每个测试类加这注解 @RunWith(GrinderRunner) class TestRunner{ public static GTest test public static HTTPRequest request // 在每个进程启动前执行 @BeforeProcess static void beforeProcess() { HTTPPluginControl.getConnectionDefaults().timeout = 8000 test = new GTest(1, "查询贷款数量") request = new HTTPRequest() grinder.logger.info("before process."); } // 在每个线程执行前执行 @BeforeThread void beforeThread() { //监听目标方法,如果打标不会生成该方法的报告 test.record(this,"loanCountTest"); // 延时生成报告 grinder.statistics.delayReports=true; grinder.logger.info("before thread."); } private NVPair[] headers() { return [ new NVPair("Content-type", "application/json;charset=UTF-8") ]; } @Test void loanCountTest(){ def json = "{\"uid\": \"1_1154249\"}"; HTTPResponse result = request.POST("http://hdai.com/query-loaning-count",json.getBytes(), headers()); grinder.logger.info(result.getText()); if (result.statusCode == 301 || result.statusCode == 302) { grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode); } else { assertThat("判断响应结果:",result.statusCode, is(200)); } } }
代码参考这篇:基于Groovy搭建Ngrinder脚本调试环境
执行测试,创建脚本
创建测试计划
执行控制面板
测试报告面板
思考:
为什么要部署多个agent?
当线程数量过多的时候,实际的压力可能不会提升。由于agent本身的瓶颈,导致压力下发不下去。 当压力测试结果表现为:线程数量增多,响应时间和tps数却无变化,说明agent本身已经达到瓶颈了,无法再增加更多的压力。 这时候就需要部署多个agent给被测服务。