利用jmeter进行压力测试
jmeter进行压力测试
推荐博客:jmeter http://www.cnblogs.com/fnng/category/345478.html
http://www.cnblogs.com/puresoul/category/736960.html
javavirtualVM 远程 https://my.oschina.net/sub/blog/223475
插件 http://blog.csdn.net/defonds/article/details/54576604
调度器 http://blog.csdn.net/java2013liu/article/details/53424545
1.压力测试的简单讲解
2.压力测试的指标、监控
3.利用jmeter进行压力测试
4.压力测试瓶颈的简单定位
1.压力测试的简单讲解
(1.)什么时候进行压力测试。
基于接口的压力测试,在接口功能测试完成之后就可进行接口的压力测试。如果有接口的依赖关系,各个接口都要完成接口的功能测试之后,再行压力测试
基于业务多场景的综合压力测试,要在所有业务功能测试通过之后进行
(2.) 压力测试的合理性
压力测试结果是否有效,还要看压力环境,举个例子: 测试环境和生产环境硬件配置没可比性,那么测试环境的压力测试毫无意义,测试报告毫无意义
在无法保证测试环境生产环境相同的配置情况下,理论要求: 单机配置相同。再举个例子:正式环境服务器10台 16G 4核 数据库 5台 那么测试环境 1台 4核 16G的服务器,数据库服务器也要和生产单台配置相同
如果有条件可以在生产环境直接进行压力测试
2.压力测试的指标
1、吞吐率(Request per second)
服务器并发处理能力的量化描述,单位是reqs/s,指的是某个并发用户数单位时间内处理的请求数。某个并发用户数下单位时间内能处理的最大请求数,称之为最大吞吐率。
记住:吞吐率是基于并发用户数的。这句话代表,1:吞吐率和并发用户数相关;2:不同的并发用户数下,吞吐率一般是不同的。
计算公式:总请求数/处理完成这些请求数所花费的时间。
Request per second=Complete requests / Time Taken for tests
2、并发连接数(The number of concurrent connections)
并发连接数指的是某个时刻服务器所接收的请求数目,简单的讲,就是一个会话。
3、并发用户数(The number of concurrent users,Concurency Level)
要注意区分这个概念和并发连接数之间的区别,一个用户可能同时会产生多个会话,也即连接数。在Http/1.1下,IE7支持两个并发连接,IE8支持6个并发连接,FireFox3支持4个并发连接,所以相应的,我们并发用户数就得除以这基数。
4、用户平均请求等待时间(Time per request)
计算方式:处理完成所有请求数所花费的时间/(总请求书/并发用户数),即
Time per request=Time Taken for tests/(Complete reuqests/Concurrency Level)
5:服务器平均请求等待时间(Time per request:across all concurrent requests)
计算公式:处理完成所有的请求数所花费的时间/总请求数,即
Time taken for/testsComplete requests
可以看到,它是吞吐率的倒数。
同时,它也等于用户请求等待时间/并发用户数,即
Time per request /Concurrency Level
3. 利用jmeter进行压力测试
1.参数化 2.关联 3.jmeter基本介绍 4.监控 5.测试报告
@@@参数化@@@
在做测试时,造的测试数据要有自己的标识,便于以后删除或查找问题,比如:yxjtest001
对于LR或jmeter而言,自己输入的值顶多需要做参数化
参数化原因:
1.逼不得已(应用程序不允许反复操作、数据库校验唯一性)
2.避免数据库的查询缓存
原因:若使用线上(已有)数据或没有参数化,会导致测试结果失真。
查询缓存:
偷懒:
1.若数据量较大,可暂时把数据库校验唯一性去掉
2.为了消除缓存影响,可把数据库缓存(cache)关掉(对于select操作)
银行流水号-------参数化
100个并发用户,并发10分钟,tps=10,1个用户跑基准测试,tps=1
Q:参数化设置?
A:那么平均给每个用户分配60个值,但是建议60以上比如80
(10*10*60/100=60,至少需要造的数据:60*100=6000)
银行流水号-------参数化
100个并发用户,并发10分钟,tps=?(无限),1个用户跑基准测试,tps=1
Q:参数化设置?
A:那么平均给每个用户分配600个值,但是建议600以上比如800
(一个用户10分钟跑的事务:1*10*60=600,至少需要造的数据:600*100=60000)
关联函数放在距离最近的可以返回关联的值的那个请求的前面
@@@关联@@@
将服务器返回的动态的变化的值,把他保存为一个参数,以供后面需要使用它的地方进行使用。
什么时候需要做关联:
1.服务器会校验该值的合法性【hash、cookie、session、token、时间戳、验证码(图片验证码、短信验证码、邮箱验证码)】
遇到 验证码 时,写js去自己解析验证码,然后再使用;
或者把验证码验证去掉(或整个万能验证码)
2.数据库打交道--后续需要对该值进行增删改查操作(此情况用的比较多)
insert操作---插入的值需要与其他表的数据建立关联/对应关系,需要进行关联
脚本回放成功,只是代表http状态码成功
查看关联函数放在哪儿,可以:
1.鼠标放在不确定放在哪儿的脚本中,点击 tree-->http View 查看response
2.抓包看,找要关联的变化的值,看其在哪个URL(即哪个URL会返回该值)
3.点击 Run-time setting-->Log-->勾选 Data returned by server
4.看脚本下方的 Generation Log
关联函数添加:
1.进入Tree 模式,response下,找到要关联的值-->右键 Create Parameter
(此种方式关联的位置是对的,且会自动把左右边界找好,但是有可能左右边界值会错,所以需要回放看一下)
2.右键 insert-->new step (或者 alt+insert)||直接点击页面顶部的 insert-->new step
3.直接从response里面找
4.抓包,看里面的左右边界值
5.通过查看源文件,找左右边界值
>如果不转义,回放时系统会默认是HTML语言的一部分,进而把其忽略掉
如果左右边界设置的值不是很精确的话(即好多地方不同的内容都匹配),系统默认取第一个取到的值,若是第一个值匹配的话还好,不匹配的话就会报错。
如果想要关联的值出现的次数较多,不确定取哪个值的左右边界时,建议取出现次数较多的。
批量替换:ctrl+h
【例子:】
登陆天猫----查看首页----浏览商品---商品添加购物车---修改商品信息----删除不要的商品---支付---查看订单--删除订单
登陆----可能需要参数化----select
查看首页--理论不需要参数化关联,精准推荐时候需要关联----select
浏览商品---有可能参数化 有可能关联 ----都是产品id----select
添加购物车---关联 商品id 用户id insert
修改商品信息---关联 商品id 用户id update
删除商品-----关联 商品id 用户id delete
支付-----insert订单 关联 订单id 用户id delete删购物车 关联商品id 用户id update 修改库存 商品id
查看订单----关联select 订单id
删除订单-----delete 关联 订单id
@@@jmeter基本使用@@@
启用 调度器,则 循环次数 不生效
CSV Date Set Config中Allow quoted data?设置 True时取的值没有引号;设置 False时取的值有引号
CSV Date Set Config中Sharing mode----All threads:标准的 唯一 + 每次迭代
线程组与线程组之间取值也不一样,严格遵循唯一
CSV Date Set Config中Sharing mode----Current thread:标准的 顺序 + 每次迭代
不同线程组之间也是顺序的
CSV Date Set Config中Sharing mode----Current thread group:基于每个线程组下的 唯一 + 每次迭代
不同线程组之间是顺序的,平行取值
Loadrunner与Jmeter相比,Loadrunner靠谱。
Loadrunner响应时间比Jmeter小,因为是C写的。
小规模并发,jmeter响应时间比LR小一些,理论上LR响应时间比jmeter短,所有要加检查点,看请求是否都成功。
大规模并发,jmeter响应时间比LR大。
LR关联有5种方法:
tree视图response中找
tree视图里邮件自动关联
lr日志里找返回值
抓包
chrome中F12
查看源文件
Python最少学到IO操作
第1种自动化:测试工具的开发
第2种自动化:测试平台的开发
在做性能压测的时候,查看结果树一般被禁用,此时可以加【断言结果】,以此来查看请求是否成功。
【响应断言】结果在查看结果树里看
Jmeter中Think-time可以靠添加【定时器】来实现
Jmeter中集合点可以靠添加【Synchronizing Time】来实现
Jmeter查看报告的话,看【聚合报告】
跟随重定向,会记录整个请求过程,包括cookie跟header,自动重定向不会。
数据库连接池有2个,一个是MySQL允许的最大值,一个是应用程序允许的。主要是看应用程序允许的最大值是多少。
比如Jmeter中要看ax Number of Connections设置的值
开发测试的值跟你的不一样(响应时间比你测的少,TPS比你的大)?
先确定软件/硬件环境、数据库里的数据量是否一致,用的测试工具是否一致?
ab或webbench不接收服务器返回值,但是LR跟jmeter会接收服务器返回值,所以会不一样。
即使用相同的工具,得出的值也会有所差异,但是不会差很多,可以取平均值。
工具里的响应时间是1.9秒,但是日志里响应时间是1.8秒?
先确定你们的响应时间是不是指的【同一个】请求,因为工具里给的时间有可能是多个请求的。
假设开发跟你看的都是一个请求,但是响应时间的值不一样,是什么原因?
开发计算的起始结束时间与你的不一样,你的话可以从负载机、网络、中间件排查是否哪里中出了问题。
@@@监控@@@@
CPU使用率高怎么办?
top命令看下CPU使用情况,然后按1看下是否所有的CPU都高,然后再看是由于刚并发导致的还是并发一段时间后出现了该现象
接着看到底是用户态进程占用CPU高还是系统态进程占用CPU高,如果是user占用高则说明用户进程消耗了,
去查看高的进程(top),再去看进程对应的线程及执行的请求;
如果是系统态占用CPU高,说明系统内核调用导致了CPU比较高,
看是否是由于磁盘繁忙(sar、nmon--discuss busyness)导致的,
如果是磁盘的话再看是读还是写导致的,若是读(磁盘往内存里读)说明有可能是内存不足导致的,
若是写操作比较高看下是谁在写操作,查看下当前系统在写什么然后减少下写操作
如果不是由磁盘引起的,使用命令strace看系统调用的哪个内核,
总结(CPU消耗高定位):
top 找出消耗最高的进程pid
top -H -p pid (找出最高的线程tid)
printf "%x\n" tid 线程tid转换成16进制B
然后拿着B去jstack dump出来的文件(nid)里查对应的方法
或者 jstack pid | grep 转换成的16进制
用户态cpu:用户进程做的事
系统态cpu:任何触发内核调用的
进程状态:running、终端可恢复状态、中断不可恢复状态、僵尸进程
top: load average-->指系统正在排队的进程已经进行的进程,简单来说就是系统负载
(系统过去1分钟的平均负载、系统过去10分钟的平均负载、系统过去15分钟的平均负载)
查看cup颗粒数-->top后按1 或 cat /proc/cupinfo
Cpu(s)-->指平均CPU使用情况,不会超过100% || 但是Cpu却可能超过100%
Swap-->指虚拟内存
NI:指CPU运行进程的优先级
按CPU排序:shift+P
按内存排序:shift+M
load average:load---等待IO的进程+等待CPU处理的进程
CPU低,负载高情况:
IO操作进程比较多,等待IO的进程多
数据库全表扫描(没有索引时),因为数据不在内存在磁盘中,要从磁盘中那数据
存活区大约是大小相等,位置互换
YGC时执行2件事:
①. 寻根判断,判断哪些是垃圾对象,哪些是存活对象(没有引用的对象属于垃圾对象,还有引用的指向属于存活对象)。
②. 进行垃圾回收,把存活对象放到第一个存活区,把垃圾对象回收。(在进行垃圾回收时,整个应用程序的线程是暂停的。)
年轻代(仅仅供参考下,不全):
串行回收:java应用线程停止,用1颗CPU进行回收
并行回收:java应用线程停止,用多颗CPU进行回收
YGC只会发生在伊甸园区(伊甸园区触发YGC),但是YGC作用的范围是伊甸园区+存活区。
以下会进入老年代区:
1.大对象
2.长期存活的对象(默认age=15-->GC15次)
3.对象动态分配(survivor空间中相同年龄的对象的大小总和大于survivor空间的一半,则从该age及以上都会晋升到老年代)
老年代满了会触发FGC,但是年轻代与老年代不同时做GC。
什么情况下会导致FGC?
1.定位内存泄漏用 jmap -dump的时候会触发FGC
2.老年代内存不足的时候
3.持久代被写满
4.System.gc()被显示调用
5.上一次GC之后Heap的各域分配策略动态变化
如果有大量的FGC就要查询是否有内存泄漏的问题了,若FGC数量比较大并且执行时间较长,就会导致系统的响应时间较长。
Full GC:
对整个堆进行整理,包括年轻代、老年代和持久代。
Full GC因为需要对整个堆进行回收,所以比YGC要慢(且会频繁占用线程),因此应该尽可能减少、延缓FGC(老年代)的次数。
GC时,java应用线程是停止的,回收之后应用程序才会继续
jmap:分析内存泄漏,dump内存使用情况的
jmap -heap pid
jmap -histo pid 内存调用情况(能定位到方法级),若前几个没有自己认识的方法,
用MAT把内存信息dump下来
jmap -histo:live pid 内存中还在引用的对象
jmap -dump:live,format=b,file=XX.bin pid 可以dump堆内存使用快照
jmap -dump 的时候会进行(触发)FGC
jstat监视垃圾回收活动情况,看YGC时间是不是太长,FGC的频率是否太高,从而对代码进行优化
jstat -gcutil pid 2000 ---2秒刷新一下数据
jstack:把栈区dump下来,分析线程栈的时候:
先搜索是否有blocked(死锁)状态(如有blocked看死锁的线程执行的方法,进而找出原因)
再看waiting状态(看waiting线程执行的方法,进而找出原因)
再看running,像什么CPU高就是running造成的
jstack pid
总结(CPU消耗高定位):
top 找出消耗最高的进程pid
top -H -p pid (找出最高的线程tid)
printf "%x\n" tid 线程tid转换成16进制B
然后拿着B去jstack dump出来的文件(nid)里查对应的方法
或者 jstack pid | grep 转换成的16进制
线程ID转换为16进制格式:
printf "%x\n" tid
线程常见几种状态:runnable running wating sleeping blocked dead
进程几种状态:running 中断可恢复状态 中断不可恢复状态 僵尸进程
硬件原因,比如CPU满或者负载非常高
用top命令查看cup、load average;iostat查看IO信息--若tps很低则代表IO没问题
【【日志要实时看,出了问题先看日志再使用top命令排除完硬件原因后,应该马上用jstack去看下线程栈】】
1.jstack 应用pid > XXX.log
2.看线程栈:vi XXX.log
3.搜索:/BLOCK 死锁原因在 at 后
数据库死锁:表现在mysql里面block
线程池死锁:在线程池里面的锁就是线程池死锁
Jmeter 比 LoadRunner快的原因:Jmeter有个长连接可勾选(User KeepAlive)
JVM参数--JVM内存大小默认64M好像是
定位内存泄漏最快的方式是用jmap
1.jmap -histo pid 内存调用情况(能定位到方法级),若前几个没有自己认识的方法,就用MAT把内存信息dump下来
2.jmap -histo pid > 1.txt
3.查看 1.txt,若在前20中没有发现认识的包/方法,就先dump一份(jmap -dump:live,format=b,file=XX.bin pid 可以dump堆内存使用快照)
4.然后sz XX.bin文件到Windows环境上,用MAT或jhat分析dump的文件,一般用MAT
5.使用MAT打开后会有2个窗口,不要看视图(Overview)而是先看报告就行
jmap -dump 的时候会进行(触发)FGC
jvisualvm dump的文件后缀是:.hprof
linux部署项目时,.war文件一般会自动解压,若系统没有给自动解压就用unzip手动解压即可
掌握JVM垃圾回收原理,能够熟练使用jmap、jstack、jhat、jstat、jconsole、jvisualvm、jprofiler 进行性能监控、问题定位及Java虚拟机的问题优化