性能测试基础02
引入
- 性能测试的各种指标结果如何获取?
- 性能测试时间一般比较长,如何获取测试过程中的所有指标数据?
聚合报告
介绍
作用:收集性能测试结束后,系统的各项性能指标。如:响应时间、并发数、吞吐量、错误率等
位置:测试计划->右键->监听器->聚合报告
参数介绍:
Label:每个请求的名称
样本:各请求发出的数量
平均值:平均响应时间(单位:毫秒)
中位数:中位数,50% <= 时间
90%百分比:90% <= 时间
95%百分比:95% <= 时间
99%百分比:99% <= 时间
最小值:最小响应时间
最大值:最大响应时间
异常%:请求的错误率
吞吐量:吞吐量。默认情况下表示每秒完成的请求数,一般认为它为TPS。
接收 KB/sec:每秒接收到的千字节数
发送 KB/sec:每秒发送的千字节数
案例
- 1、请求:https://www.baidu.com
- 2、模拟5个用户并发,控制服务器QPS为20,运行时长设置为10分钟
- 3、添加聚合报告,收集系统性能指标:响应时间、吞吐量、错误率、网路速率
html测试报告
介绍
作用:JMeter支持生成HTML测试报告,以便从测试计划中获得图表和统计信息
命令:
jmeter -n -t [jmx file] -l [result file] -e -o [html report folder]eg:
jmeter -n -t hello.jmx -l result.jtl -e -o ./report
参数描述:
- -n:非GUI模式执行JMeter
- -t [jmx file]:测试计划保存的路径及.jmx文件名,路径可以是相对路径也可以是绝对路径
- -l [result file]:保存生成测试结果的文件,jtl文件格式
- -e:测试结束后,生成测试报告
- -o [html report folder]:存放生成测试报告的路径,路径可以是相对路径也可以是绝对路径
- 注意:result.jtl 和 report 会自动生成,如果在执行命令时 result.jtl 和 report 已存在,必须用先删除,否则在运行命令时就会报错
练习
- 1、请求:https://www.baidu.com
- 2、模拟5个用户并发,控制服务器QPS为20,运行时长设置为10分钟
- 3、使用命令行的方式运行,并收集HTML测试报告
测试报告
- HTML测试报告:执行完毕后,用浏览器打开生成报告的文件目录下的index文件,效果展示如下

APDEX (应用性能指标):
APDEX:满意度,范围在 0-1 之间,1表示达到所有用户均满意
T(Toleration threshold):容忍或满意阈值
F(Frustration threshold):失败阈值
Requests Summary(请求总结):
- 成功与失败的请求占比,KO指失败率,OK指成功率
HTML测试报告:
- Chart(详细信息图表):它包括Throughput(吞吐量) 、Response Times(响应时间)等
每秒事务数,即 TPS :

- Response Times Over Time(脚本运行期间的响应时间变化趋势图)

小结
- (1)聚合报告的核心内容有哪些?
- 响应时间、吞吐量、错误率、网路速率
- (2)JMeter生成html测试报告的命令?
jmeter -n -t hello.jmx -l result.jtl -e -o ./report- 注意事项:
- 如果在执行命令时result.jtl和report已存在,必须用先删除
- (3)JMeter的HTML测试报告的内容?
- 性能统计仪表盘
- 性能测试过程中的详细信息报表
TPS计算
引入
稳定性测试时需要模拟用户真实负载量,真实负载量是多少?
压力测试时需要模拟高负载验证系统的容错能力,高负载有多高?
性能测试时的TPS,大都是根据用户真实的业务数据(运营数据)来计算的
运营数据:

- PV:(Page View)即页面访问量,每打开一次页面PV计数+1,刷新页面也是。PV只统计页面访问次数。
普通计算
计算公式:TPS = 总请求数 / 总时间
数据分析:
- 根据数据统计,在2019年第32周,日均PV为4.13万,可以估算为1天有4.13万请求(1次浏览都至少对应1个请求)
- 总请求数 = 4.13 万请求数 = 41300
- 总时间 = 1天 = 1 * 24 小时 = 24 * 3600 秒
套入公式:
- TPS = 41300请求数/24*3600秒 = 0.48请求数/秒
结论:按照普通计算方法,理论上每秒能够处理0.48请求,就可以满足线上的需要。
二八原则计算
二八原则就是指80%的请求在20%的时间内完成
计算公式:
TPS = 总请求数 * 80% / (总时间*20%)套入公式:
TPS = 41300 * 0.8请求数 / 24*3600*0.2秒 = 1.91 请求数/秒
结论:按照二八原则计算,在测试环境我们的TPS只要能达到1.91请求数每秒就能满足线上需要。二八原则的估算结果会比平均值的计算方法更能满足用户需求。
计算稳定性测试并发量

数据分析:
根据这些数据统计图,可以得出结论:
大部分订单在8点-24点之间,因此系统的有效工作时长为16个小时
从订单数量统计,8-24点之间的订单占一天总订单的98%左右(40474个)
结合二八原则计算公式 :
TPS = 总请求数 * 80% / (总时间*20%):- 需要在测试环境模拟用户正常业务操作(稳定性测试)的并发量为:
TPS = 40474 * 0.8请求数 / 16*3600*0.2秒 = 2.81 请求数/秒
- 需要在测试环境模拟用户正常业务操作(稳定性测试)的并发量为:
计算压力测试并发量

数据分析:
- 根据这些数据统计图,可以得出结论:
- 订单最高峰在在21点-22点之间,一小时的订单总数大约为 8853个
- 根据这些数据统计图,可以得出结论:
计算压力测试的并发数:
TPS = 峰值请求数/峰值时间 * 系数:
需要在测试环境模拟用户峰值业务操作(压力测试)的并发量为:
TPS = 8853 请求数 / 3600秒 * 3(系数) = 7.38 请求数/秒
小结
(1)并发数计算方法有哪几种?作用有什么区别?
普通方法:
并发数TPS = 总请求数/总时间
作用:可以满足系统最最基本的应用场景(每天的总请求数)的要求。
二八原则:
- 并发数TPS = 总请求数 * 80% / 总时间 * 20%
- 作用:可以满足绝大多数情况下,用户真实的业务场景要求。
根据业务运营数据的统计计算(通常用来做稳定性测试)
- 并发数TPS = 有效请求数 * 80% / 有效时间 * 20%
- 作用:可以满足绝大多数情况下用户真实的业务场景要求(当运营数据的统计越精确,计算结果越准确)
根据用户峰值业务操作来计算(通常用来做压力测试)
- 并发数TPS = 峰值请求数 / 峰值时间 * 系数
- 作用:专门用于满足极端的用户业务场景下的性能需求
第三方插件
引入
- JMeter自带监控功能无法监控服务器资源怎么办?
- JMeter自带的报告不能精确统计运行过程中的性能指标变化怎么办?
插件安装
说明:先下载JMeter插件管理工具包,再用此包下载JMeter插件
下载插件管理包的步骤:
- 下载包管理工具jar包
- 将包管理工具jar包添加到JMeter放入到lib\ext目录下
- 重启JMeter,可以在选项下看到插件管理


- 安装第三方插件的步骤:
- 打开Plugins Manager插件管理器
- 选择Available Plugins,当前可用的插件
- 选择需要下载的插件(等待右方文本内容展示出来)
- 下载右下角的下载按钮,自动的完成下载,JMeter会自动重启

案例
1、安装插件管理包
2、安装如下指定的插件
3 Basic Graphs
5 Additionally Graphs
Custom Thread Groups
PerfMon
小结
- (1)第三方插件的作用?
- 使用第三方开发的扩展功能
- (2)第三方插件的下载步骤?
- 下载插件管理器:
- 下载包管理工具jar包
- 将包管理工具jar包添加到JMeter放入到lib\ext目录下
- 重启JMeter
- 下载第三方插件:
- 打开Plugins Manager插件管理器
- 选择Available Plugins,当前可用的插件
- 选择需要下载的插件(等待右方文本内容展示出来)
- 下载右下角的下载按钮,自动的完成下载,JMeter会自动重启
- 下载插件管理器:
性能测试常用图表
Concurrency Thread Group 线程组
- 阶梯线程组:作用是阶梯加压;图形界面显示运行状态
- 添加方式:测试计划 –> 线程(用户)–> Concurrency Thread Group

- 参数介绍:
Target Concurrency:目标并发(线程数)
Ramp Up Time:加速时间
Ramp-Up Steps Count:加速步骤计数
Hold Target Rate Time:运行时间
Time Unit:时间单位(分钟或者秒)
Thread Iterations Limit:线程循环次数
Log Threads Status into File:日志记录
Transactions per Second
- 每秒完成事务数:作用是统计各个事务每秒钟成功的事务个数
- 添加方式:测试计划 –> 线程组–> 监听器–>Transactions per Second

Bytes Throughput per Second
- 每秒字节吞吐量:作用是查看服务器吞吐流量(单位/字节)
- 添加方式:测试计划 –> 线程组–> 监听器–>Bytes Throughput Over Time

案例
- 1、请求:https://www.baidu.com
- 2、模拟5个用户并发,控制服务器QPS为20,运行时长设置为10分钟
- 3、添加性能测试常用图表
小结
- (1)Concurrency Thread Group 线程组的作用是什么?
- 阶梯加压
- 图形界面显示运行状态
- (2)Transactions per Second和Bytes Throughput per Second有什么作用?
- Transactions per Second:作用是统计各个事务每秒钟成功的事务个数
- Bytes Throughput per Second:作用是查看服务器吞吐流量
- (3)Transactions per Second和聚合报告中的TPS在性能测试时的作用有何不同,以哪个为准?
- 性能测试的结果统计,以聚合报告的结果为准
- 每秒性能指标的作用是:查看系统长时间运行过程中是否有异常出现,有则进一步分析
PerfMon组件监控服务器资源
介绍
- 作用:用来监控服务端的性能资源指标的工具,包括cpu、内存、磁盘、网络等性能数据
- 添加方法:线程组->监听器->jp@gc - PerfMon Metrics Collector
- 注意:使用之前需要在服务器端安装监听服务程序并启动

监控资源指标步骤
- 监控服务器资源指标的步骤:
下载安装包ServerAgent-2.2.3.zip,链接地址:https://github.com/undera/perfmon-agent
上传到服务器上,并解压ServerAgent-2.2.3.zip
启动,如果是windows运行startAgent.bat,如果是linux运行startAgent.sh
启动这个工具后,jmeter的插件jp@gc - PerfMon Metrics Collector就可以收集服务端的资源使用率,并在 jmeter中查看了

案例一
- 1、启动windows上安装的Tpshop商城项目
- 2、使用JMeter编写脚本,访问首页,控制运行时间为60s,并同步监控服务器资源指标
- 操作步骤:
- 上传ServerAgent-2.2.3.zip到windows服务器上,并进行解压
- 启动ServerAgent程序startAgent.bat
- 添加线程组,配置持续时间为60s
- 添加HTTP请求 – 首页
- 添加PerFMon组件
- 添加聚合报告
案例二
- 1、启动linux上安装的Tpshop商城项目
- 2、使用JMeter编写脚本,访问首页,控制运行时间为60s,并同步监控服务器资源指标
- 操作步骤:
- 上传ServerAgent-2.2.3.zip到linux服务器上,并进行解压
- 启动ServerAgent程序startAgent.sh
- 添加线程组,配置持续时间为60s
- 添加HTTP请求 – 首页
- 添加PerFMon组件
- 添加聚合报告
小结
- (1)PerfMon组件的作用?
- 用来监控服务端的性能资源指标,包括cpu、内存、磁盘、网络等性能数据
- (2)PerFMon组件监服务器控资源指标的步骤?
- 下载ServerAgent-2.2.3.zip,并上传到服务器上进行解压
- 启动ServerAgent程序
- 如果是windows运行startAgent.bat
- 如果是linux运行startAgent.sh
- 编写JMeter脚本,配置运行时间
- 添加PerFmon组件
- 服务器IP
- ServerAgent程序端口
- 待监控的指标
项目实战
项目背景
- 轻商城项目是一个现在流行的电商项目。我们需要综合评估该项目中各个关键接口的性能,并给出优化建议,以满足项目上线后的性能需要。
项目功能架构
- 前台商城:购物车、订单、支付、优惠券等
- 后台管理系统:商品管理、会员管理、商场管理、推广管理等

项目技术架构
- 前端:VUE技术框架开发,支持微信小程序、手机移动端、web界面
- 后端:SpringBoot框架开发,MySQL做数据库

数据库设计
作用:
熟悉数据库设计结构,便于后期对数据库的性能监控,方便问题定位
构造性能测试数据

轻商城项目搭建
- 准备工作:安装JDK、MySQL、Nginx

性能测试需求分析
获取需求
客户方提出:
- 能够提出明确需求的一般是金融、银行、电信、医疗等企业,他们一般对系统的性能要求高,并且对性能也非常了解
根据历史运营数据分析,如:
用户频繁使用的功能模块是哪些
每月、每周、每天的峰值业务量是多少
竞品分析:
- 对比同类型软件的性能指标结果
提取性能测试点
业务维度提取:
用户频繁使用的业务功能
非常关键的业务功能
特殊交易日或峰值交易的业务功能
核心业务发生重大调整的业务功能
技术维度提取:
- 资源占用非常高的业务功能

确定性能测试目标
- 轻商城作为一个新开发的项目,性能测试目标包括:
确定核心业务功能的TPS
对业务流程(多接口组合)进行压测
系统能在实际系统运行压力的情况下,稳定的运行24小时

性能测试计划及方案
掌握如何编写测试计划
测试计划核心内容:
测试背景
测试目的
- 确定核心业务功能的TPS
- 对业务流程(多接口组合)进行压测
- 系统能在实际系统运行压力的情况下,稳定的运行24小时
测试范围
测试策略
- 基准测试:先做基准测试,确定估算的标准
- 负载测试:分别模拟5、10、30、50、100个用户对系统进行负载测试,查看不同并发时系统软件各项指标是否符合需求
- 稳定性测试:用200用户对系统进行7*24小时的不间断稳定性测试
风险控制
交付清单
进度与分工


性能测试用例设计

性能测试执行
编写测试脚本
常用测试元件:
- 取样器-HTTP请求
- 配置元件-HTTP请求默认值
- 配置元件-用户定义的变量
- 后置处理器-JSON提取器
- 断言-响应断言
- 断言-JSON断言
- 监听器-察看结果树
- 监听器-聚合报告
JMeter脚本的基本结构:
创建测试用例结构
设置HTTP请求默认值
用户定义的变量
添加监听器-察看结果树
添加监听器-聚合报告

使用JMeter实现测试用例
例如:获取首页数据
操作步骤:
在线程组下,添加取样器‘HTTP请求-获取首页数据’,并填写请求数据
在取样器下,添加‘响应断言’断言响应状态码
在取样器下,添加 ‘JSON断言’ 断言 errno 和 errmsg
发送请求,调试脚本




搭建测试环境
性能测试环境的特点
- 独占性
- 尽量保持性能测试环境与真实生产环境的一致性
- 硬件环境
- – 包括服务器环境、网络环境等
- 软件环境
- – 版本一致性:包括操作系统、数据库、被测应用程序、第三方软件等
- – 配置一致性:包括操作系统、数据库、被测应用程序、第三方软件等
- 使用场景的一致性
- – 基础业务数据的一致性
- – 业务操作模式的一致性:尽量模拟真实场景下用户的使用情况
- 硬件环境
构造性能测试数据
- 目的:压测环境中的数据量尽量与生产环境中数据量一致
- 方法:为了快速创建大量数据,可以直接操作数据库进行添加
- 准备插入数据的SQL语句
- 循环执行SQL语句来插入数据
- 导包
- 连接数据库
- 创建游标
- 执行SQL语句
- 关闭游标
- 关闭连接
案例-构建大量数据
- 通过编写Python脚本,构造10万条商品记录
- 操作步骤:
- 准备插入数据的SQL语句
- 循环执行SQL语句来插入数据

监控性能测试指标
- 性能测试的基础指标指标:
- 系统指标:
- 响应时间
- 并发数
- 吞吐量
- 错误率
- 服务器资源指标
- CPU使用率:一般可接受上限为85%
- 内存利用率:一般可接受上限为85%
- 磁盘I/O
- 网络带宽
- 系统指标:


执行性能测试脚本
- 单台测试机执行:
- 前提:先保证脚本调试通过之后,才能进入正式压测阶段。
- 可以选择Windows或者Linux测试机来执行:
- Windows环境:操作界面化、直观、易上手,但是软件占用机器资源较多,导致资源使用率不高;可支持并发较低。
- Linux环境:命令行操作,结果查看不太方便,但资源利用率相对较高;可支持较高并发。
- 分布式执行:
- 如果单台压测机的并发量不能够满足要求,则可以通过分布式压测来提高并发量。
- JMeter工具支持分布式压测,即多台机器同时执行同一个脚本,然后统计结果。
性能分析和调优
性能调优的步骤
确定问题:根据性能监控的数据和性能分析的结果,确定性能存在的问题(要求)
确定原因:确定了问题之后,对问题进行分析,找出问题产生的原因
给出解决方案:确定调整目标和解决方案(改服务器参数配置/增加硬件资源配置/修改代码)
验证问题:按照给出的解决方案,重新进行测试
分析调优结果:分析出问题的性能指标是否有提升,关注其他指标未下降
- 注意:性能测试调优并不是一次完成的过程,针对同一个性能问题,上面的五步可能要经过多次循环才能最终完成性能调优的目标(即:测试发现问题-找原因-调整-验证-分析-再测试。。。)
性能瓶颈分析
介绍
在实际的性能测试中,会遇到各种各样的问题,比如TPS压不上去,导致这种现象的原因很多,作为测试人员应配合开发人员进行分析尽快找出瓶颈的所在。
常见的性能瓶颈分析:
服务器资源分析
- CPU瓶颈:CPU已压满(接近100%),通常其他指标的拐点出现的时刻是否与CPU压满的时刻基本一致
- 内存瓶颈:内存不足时,操作系统会使用虚拟内存,从虚拟内存读取数据,影响处理速度
- 磁盘I/O瓶颈:磁盘I/O成为瓶颈时,会出现磁盘I/O繁忙,导致交易执行时在I/O处等待
- 网络带宽:如果传递的数据包过大,超过了带宽的传输能力,就会造成网络资源竞争,导致TPS上不去
JVM瓶颈分析
- JVM内存:内存申请没有及时释放,造成内存泄漏
数据库瓶颈分析
- 慢查询
- 数据库的连接池:设置太小,导致数据库连接出现排队
- 数据库出现死锁
程序内部实现机制
压测机
- JMeter单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,也会导致TPS压不上去
CPU瓶颈
- 每个程序运行都需要占用CPU,那么单CPU的机器是如何同时运行多个程序的?
- 时间片即CPU分配给各个程序的时间,每个程序被分配一个时间段,称作它的时间片,即该程序允许运行的时间

- CPU使用率:
- 表示一段时间内,正在使用的CPU时间段 / 总的CPU时间段 * 100% ,
- CPU使用率分为用户态、系统态和空闲态
- 用户态:表示 CPU 处于应用程序执行的时间
- 系统态:表示系统内核执行的时间
- 空闲态:表示空闲系统进程执行的时间

- 查看CPU使用率的命令:
top - 测试关注点:
- 当CPU使用率高时,确定是用户CPU高,还是系统CPU高
- 如果是用户CPU高,说明某个软件程序的CPU资源占用率高,需要定位代码程序运行的效率
- 如果是系统CPU高,同步观察是否是其他资源(磁盘IO、内存、网络等)不足
内存和虚拟内存
- 内存:又称主存储器/物理内存,计算机中所有程序的运行都在内存中进行
- 虚拟内存:是计算机系统内存管理的一种技术。当计算器内存不足时,可以使用虚拟内存进行补偿
- 在程序运行时,可以将程序的一部分装入内存,而将其余部分留在外存(磁盘),就可以启动程序执行。
- 在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。
- 同时,操作系统将内存中暂时不使用的内容换出到外存上,从而腾出空间存放将要调入内存的信息。
- 这样,系统好像为用户提供了一个比实际内存大得多的存储器,称为虚拟存储器。

内存瓶颈
- 内存瓶颈:内存不足时,操作系统会使用虚拟内存,从虚拟内存读取数据;而内存的速度要远快于磁盘速度,因此使用虚拟内存时性能大大降低。
- 查看内存使用的命令:
vmstat

Swap:
- si: 每秒从交换区写到内存的大小
- so: 每秒写入交换区的内存大小
测试关注点:
- 如果si,so 长期不等于0,表示内存不足。(需要大量的从内存和虚拟内存之间读来读去,说明内存盛不开那么多进程,说明内存不足)
磁盘IO瓶颈
- 磁盘IO瓶颈:影响性能的是磁盘的读写速度(Input和Output速率),不是磁盘大小。
- 查看磁盘IO使用的命令:
iostat -x 1 1

Ø %util: 表示一秒中有百分之多少的时间用于 I/O
Ø %iowait:CPU等待输入输出完成时间的百分比。
测试关注点:
- Ø 如果%util接近100%,说明产生的I/O请求太多,I/O系统已经满负荷
- Ø 如果%iowait的值过高,表示硬盘存在I/O瓶颈
网络瓶颈
- 网络瓶颈:影响性能的是网络的传输速度,与网络的总带宽进行对比,接近总带宽,说明网络存在瓶颈。
- 查看网络使用的命令:
sar -n DEV 1 2

Ø rxkB/s: 每秒接收的数据量(千字节数)
Ø txkB/s: 每秒发送的数据量(千字节数)
测试关注点:
- Ø 将每秒接收的数据量rxkB/s,与网络最大带宽进行对比,如果实际传输速率接近网络最大带宽,说明网络IO有瓶颈
慢查询
- 慢查询定义:指执行速度低于设置的阀值的SQL语句
- 作用:帮助定位查询速度较慢的SQL语句,方便更好的优化数据库系统的性能
- MySQL慢查询参数介绍:
- Ø slow_query_log: 慢查询日志开启状态[ON:开启,OFF:关闭]
- Ø slow_query_log_file: 慢查询日志存放位置

- long_query_time: 慢查询时长设置(超过该时长才会被记录,单位:秒)

- 慢查询开启并配置:
- Ø
mysql> set global slow_query_log='ON';#开启慢查询日志 - Ø
mysql> set global slow_query_log_file='/data/slow_query.log';#设置慢查询日志存放位置 - Ø
mysql> set global long_query_time=1;# 设置慢查询时间标准,设置之后会在下次会话才生效
- Ø
- 查看慢查询日志:
- Ø 打开慢查询开关后,就可以记录系统运行时查询时间长的SQL语句,并同步在日志文件中查看慢查询的SQL

数据库连接池
- 为什么要使用数据库连接池?

- 数据库连接池定义:数据库连接池是负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
- 作用:可以提高对数据库操作的性能

当客户请求数据库连接时
- 首先查看连接池中是否有空闲连接,如果存在空闲连接,则将连接分配给客户使用;
- 如果没有空闲连接,则查看当前所开的连接数是否已经达到最大连接数,如果没达到就重新创建一个连接给请求的客户;
- 如果达到就按设定的最大等待时间进行等待
- 如果超出最大等待时间,则抛出异常给客户
测试关注点:
- Ø MYSQL官网给出了一个设置最大连接数的建议比例:Max_used_connections / max_connections * 100% ≈ 85%,需要关注MYSQL的最大连接数 和 系统运行时数据库已建立连接数的比例
- Ø 如果已使用连接数与最大连接数比例超过85%,需要增加最大连接数设置,否则会造成连接失败
- Ø 如果已使用连接数与最大连接数比例小于10%,那显然设置的过大,会造成系统资源的浪费

数据库死锁
- MySQL主要有两种锁:表级、行级。
- Ø 表级锁:开销小,加锁快;不会出现死锁;锁定粒度最大,并发度最低。
- Ø 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,并发度也最高。
- 死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。
- Ø 若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁。
- Ø 表级锁不会产生死锁
- 死锁案例:
- l 投资功能,A和B两人分别给用户1给用户2进行投资

- 测试关注点(初步确定死锁):
- Ø show open tables where in_use>=1 查询当前是否锁表
- • 如果表锁了,这个sql可以查询出来
- • 但是这个sql查出来的表,不一定是被锁住的。因为用查询,如果耗费时间很长,也会查询出来
- Ø show processlist:查看执行时间最长的线程,找到对应sql,找到表
- Ø show open tables where in_use>=1 查询当前是否锁表


- kill process_id:如果需要先紧急解决问题,可以先手动杀死死锁的连接
JVM内存
JVM内存:Java 虚拟机在执行 Java 程序的过程中所管理的不同的内存数据区域。可简单分为:堆内存和非堆内存
Ø 堆内存:主要存放用new关键字创建的对象,所有对象实例以及数组都在堆上分配。 —— 给开发人员使用的(关注)
Ø 非堆内存:保存虚拟机自己的静态数据,存放加载的Class类级别静态对象如类、方法等。 —— 给JVM自己使用的
JVM堆内存的管理机制(JAVA垃圾回收机制):
- 年轻代存储“新生对象”,我们新创建的对象存储在年轻代中。
- 当年轻内存占满后,会触发Minor GC,清理年轻代内存空间。
- 老年代存储长期存活的对象和大对象。年轻代中存储的对象,经过多次GC后仍然存活的对象会移动到老年代中进行存储。
- 老年代空间占满后,会触发Full GC。Full GC是清理整个堆空间,包括年轻代和老年代

JVM内存分析
常见的内存问题:
- l 内存泄漏:
- Ø 内存泄露 memory leak,是指程序在申请内存后,无法完全释放已申请的内存空间。
- Ø 一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
- l 内存溢出:
- Ø 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out ofmemory
- Ø memory leak会最终会导致out of memory!
- l 内存泄漏:
测试关注点:
- 堆内存使用量持续增长 —— 可能是内存泄漏
- Full GC比较慢,执行时会停止程序一些事务的处理。因此Full GC频率不能过高(低于10分钟)
- 如果Full GC之后,堆中仍然无法存储对象,就会出现内存溢出 —— 程序出现crash(崩溃)

JVM内存监控
JVM监控 —— 使用本地jvisualvm远程监控服务器:
添加应用程序启动参数,并启动服务

- 进入本地jdk安装目录bin目录,找到jvisualvm.exe并启动
- 右键“远程”选择“添加远程主机”,并输入主机IP

- 右键主机选择“添加JMX连接”,并输入JMX端口

- 连接成功后在主机下会有对应的连接显示,双击查看监控信息

压测机
- 压测机影响性能测试结果的原因主要是:
- Ø JMeter单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,也会导致TPS压不上去
- 压测机资源的监控方法:
- Ø Windows测试机:自带“任务管理器”
- Ø Linux测试机:PerfMon组件
- 解决方案:
- Ø 采用分布式执行的方法来提高负载量,达到系统性能测试要求的TPS
小结
- 常见的性能问题主要有哪些方面?
服务器资源分析
CPU瓶颈:用户CPU和系统CPU
内存瓶颈:实际内存和虚拟内存
磁盘IO瓶颈:磁盘input和output
网络瓶颈:网络上下行带宽
数据库瓶颈分析
慢查询
数据库连接池
死锁
JVM瓶颈分析
- JVM内存:堆内存和内存回收
程序内部实现机制
压测机
性能调优案例
案例1_获取首页数据
场景描述:
- Ø 进入首页后,加载首页的相关数据,包括:轮播图、频道、优惠券、团购专区、品牌商直供、新品首发、热卖商品、专题精选等数据
测试结果数据 :

- 问题分析:
- CPU已接近100%
- 一次请求中需要查询很多数据
- 解决方案:
- Ø 提升服务器配置
- Ø 分批次、异步加载首页数据,首页底部的数据(如:新品首发、热卖商品、专题精选等数据)等用户向下滑动页面时再加载
案例2_ 查看商品详情
- 场景描述:
- Ø 进入商品详情页面时,加载商品的详细信息
- 测试结果数据:

- 问题分析:
- 网络带宽已跑满
- 一次请求中返回了全部数据
- 解决方案:
- Ø 提升服务器网络带宽
- Ø 分批次、异步加载商品数据
案例3_搜索商品
- 场景描述:
- Ø 进入首页,在搜索框中输入关键字搜索商品
- 测试结果数据:
- Ø 搜索关键字“床”时,出现慢查询SQL语句
- Ø 查看慢查询语句
cat /var/lib/mysql/localhost-slow.log,包含如下SQL语句

- 问题分析:
- 找出搜索商品接口对应的SQL语句(通过查看代码实现或者从日志中获取查询SQL)。如右图日志信息:
- 分析具体的SQL语句


- 问题分析:
- Ø 当搜索关键字匹配到大量的商品时,第3条SQL语句会返回大量重复数据
- Ø 第4条SQL语句中的in查询条件中同样包含大量重复的商品分类id
- Ø 因此:第4条SQL会出现查询时间较长,是由于第3条SQL返回的ID有大量重复
- 解决方案:
- Ø 优化第3条SQL语句,因该SQL语句的查询结果大部分都是重复的,可以进行去重处理

案例4_JVM内存溢出
场景描述:
- Ø 请求测试接口(/wx/index/oom),模拟内存溢出
测试结果数据:

- 问题分析:
- JVM内存占用随着时间的推移占用越来越多,直至内存溢出,系统退出
- 解决方案:
- Ø 排查代码存在的问题,及时释放无用的对象
性能测试报告
- 测试报告核心内容:
测试过程回顾 ——测试目的、测试范围、测试环境、测试使用的工具
测试问题记录及结果分析 —— 性能测试过程中遇到的问题,分析过程和解决方案
测试结论
经验总结和教训
Locust框架
学习目标
- 掌握如何使用Locust进行接口性能测试
Locust介绍和安装
Locust特点
- Ø 基于Python的开源负载测试工具
- Ø 支持多种操作系统
- Ø 支持二次开发
- Ø 能够模拟更多用户
- Ø 基于协程(微线程)的并发
Locust 与 JMeter对比

Locust安装
- 前提:已安装pycharm、python3.5以上的版本
- Ø 在线安装: pip install locustio==0.12.2
- Ø 离线安装
- Ø Pycharm安装
演示环境接口说明
登录
- URL: http://bms-test.itheima.net/bms/login
- 请求方式:POST
- 请求参数:{“username”: “admin”, “password”: “123456”}
首页
- URL:http://bms-test.itheima.net/bms/index
- 请求方式:GET
获取用户信息
- URL:http://bms-test.itheima.net/bms/profile
- 请求方式:GET
退出
请求方式:POST
编写Locust测试脚本
测试脚本实现步骤
- 1、定义任务发送HTTP接口请求。
- 2、定义任务集定义一个用户行为,包含多个HTTP请求(即具体的任务)。
- 3、定义Locust类Locust类代表用户,用户会对应具体的用户行为(即任务集)
定义任务
locust里发送请求是基于requests实现的,请求方法、参数、响应对象和requests使用方式一样
代码的案例:
1 | def index(l): |
定义任务集
定义一个用户行为(任务集),包含多个具体的任务。
定义方式:
- • 定义一个用户行为类,要继承TaskSet类,表示一个任务集
- • tasks:用来添加任务,它是一个dict类型,key表示任务的方法名,value表示挑选执行的权重,数值越大执行频率越高
- • on_start:前置方法(前置任务),在所有任务之前调用
- • on_stop:后置方法(后置任务),当任务集停止时调用
代码案例 :
1 | from locust import TaskSet |
定义Locust类
定义一个Locust类,这个类代表用户。
定义方式:
- • 自定义的Locust类继承了
HttpLocust类,这个类代表用户 - • task_set:该属性指向
TaskSet类,定义用户的行为 - • min_wait:用户执行任务之间等待时间的下界,默认值:1000ms
- • max_wait:用户执行任务之间等待时间的上界,默认值:1000ms
- • host:被测应用的网址,例如:http://bms-test.itheima.net
- • weight:用户被选中的概率,权重越大,被选中的机会就越大。默认值:10
- • 自定义的Locust类继承了
代码案例
1 | from locust import HttpLocust |
运行Locust脚本
运行Locust脚本
- 运行命令:
locust -f locust_files/my_locust_file.py --host=http://example.com
- 参数介绍:
- Ø -f:用来指定locust文件所在路径
- Ø –host:用来指定测试应用的网址
打开Locust的web界面
- 运行Locust脚本后,打开浏览器并访问:http://localhost:8089。可以看到如下界面:
- 参数介绍:
- Ø Number of users to simulate:要模拟的用户数量
- Ø Hatch rate (users spawned/second):孵化率(用户生成/秒),即每秒启动虚拟用户数
- Ø 点击Start swarming 开始运行性能测试

Statistics界面
- 类似于JMeter中的聚合报告:

Charts界面
- 测试结果变化趋势的曲线展示图。分别为:每秒完成的请求数(RPS)、响应时间、不同时间的虚拟用户数

Failures界面
- 失败请求的展示界面,即服务器原因导致无法处理请求。

Exceptions界面
- 异常请求的展示界面

Download Data界面
- 测试数据下载模块, 提供三种类型的CSV格式的下载,分别是:Statistics CSV、responsetime CSV、failures CSV、exceptions CSV


- 感谢你赐予我前进的力量
