zoukankan      html  css  js  c++  java
  • 利用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 " 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 " tid 线程tid转换成16进制B
    然后拿着B去jstack dump出来的文件(nid)里查对应的方法
    或者 jstack pid | grep 转换成的16进制

    线程ID转换为16进制格式:
    printf "%x " 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虚拟机的问题优化

          

      

    A wise man thinks all that he says, a fool says all that he thinks.
  • 相关阅读:
    Android笔记之添加退出确认对话框
    Android笔记之menu与ActionBar使用
    Android学习笔记之File存储(sd卡)
    cron 在线 表达式
    springboot
    mybatis 查询标签
    div display 常用属性
    css height VS min-height
    struts标签 解析html标签
    CSS 后代选择器
  • 原文地址:https://www.cnblogs.com/BernieChen/p/7422223.html
Copyright © 2011-2022 走看看