# JMeter测试报告

引入

  • 性能测试的各种指标结果如何获取?
  • 性能测试时间一般比较长,如何获取测试过程中的所有指标数据?

聚合报告

介绍

  • 作用:收集性能测试结束后,系统的各项性能指标。如:响应时间、并发数、吞吐量、错误率等

  • 位置:测试计划->右键->监听器->聚合报告

  • 参数介绍:

    • 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文件,效果展示如下

image-20240114175635392

  • APDEX (应用性能指标):

    • APDEX:满意度,范围在 0-1 之间,1表示达到所有用户均满意

    • T(Toleration threshold):容忍或满意阈值

    • F(Frustration threshold):失败阈值

  • Requests Summary(请求总结):

    • 成功与失败的请求占比,KO指失败率,OK指成功率
  • HTML测试报告:

    • Chart(详细信息图表):它包括Throughput(吞吐量) 、Response Times(响应时间)等
  • 每秒事务数,即 TPS :

image-20240114175747693

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

image-20240114175804018

小结

  • (1)聚合报告的核心内容有哪些?
    • 响应时间、吞吐量、错误率、网路速率
  • (2)JMeter生成html测试报告的命令?
    • jmeter -n -t hello.jmx -l result.jtl -e -o ./report
    • 注意事项:
      • 如果在执行命令时result.jtl和report已存在,必须用先删除
  • (3)JMeter的HTML测试报告的内容?
    • 性能统计仪表盘
    • 性能测试过程中的详细信息报表

TPS计算

引入

  • 稳定性测试时需要模拟用户真实负载量,真实负载量是多少?

  • 压力测试时需要模拟高负载验证系统的容错能力,高负载有多高?

  • 性能测试时的TPS,大都是根据用户真实的业务数据(运营数据)来计算的

  • 运营数据:

image-20240114180012012

  • 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请求数每秒就能满足线上需要。二八原则的估算结果会比平均值的计算方法更能满足用户需求。

计算稳定性测试并发量

image-20240114180410714

  • 数据分析:

    • 根据这些数据统计图,可以得出结论:

      • 大部分订单在8点-24点之间,因此系统的有效工作时长为16个小时

      • 从订单数量统计,8-24点之间的订单占一天总订单的98%左右(40474个)

  • 结合二八原则计算公式 : TPS = 总请求数 * 80% / (总时间*20%)

    • 需要在测试环境模拟用户正常业务操作(稳定性测试)的并发量为:
      • TPS = 40474 * 0.8请求数 / 16*3600*0.2秒 = 2.81 请求数/秒

计算压力测试并发量

image-20240114180520619

  • 数据分析:

    • 根据这些数据统计图,可以得出结论:
      • 订单最高峰在在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,可以在选项下看到插件管理

image-20240114182908868

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

image-20240114182945606

案例

  • 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

image-20240114183215225

  • 参数介绍:
    • 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

image-20240114183249657

Bytes Throughput per Second

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

image-20240114183313096

案例

  • 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
  • 注意:使用之前需要在服务器端安装监听服务程序并启动

image-20240114183623799

监控资源指标步骤

  • 监控服务器资源指标的步骤:
    • 下载安装包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中查看了

image-20240114183715662

案例一

  • 1、启动windows上安装的Tpshop商城项目
  • 2、使用JMeter编写脚本,访问首页,控制运行时间为60s,并同步监控服务器资源指标
  • 操作步骤:
    1. 上传ServerAgent-2.2.3.zip到windows服务器上,并进行解压
    2. 启动ServerAgent程序startAgent.bat
    3. 添加线程组,配置持续时间为60s
    4. 添加HTTP请求 – 首页
    5. 添加PerFMon组件
    6. 添加聚合报告

案例二

  • 1、启动linux上安装的Tpshop商城项目
  • 2、使用JMeter编写脚本,访问首页,控制运行时间为60s,并同步监控服务器资源指标
  • 操作步骤:
    1. 上传ServerAgent-2.2.3.zip到linux服务器上,并进行解压
    2. 启动ServerAgent程序startAgent.sh
    3. 添加线程组,配置持续时间为60s
    4. 添加HTTP请求 – 首页
    5. 添加PerFMon组件
    6. 添加聚合报告

小结

  • (1)PerfMon组件的作用?
    • 用来监控服务端的性能资源指标,包括cpu、内存、磁盘、网络等性能数据
  • (2)PerFMon组件监服务器控资源指标的步骤?
    • 下载ServerAgent-2.2.3.zip,并上传到服务器上进行解压
    • 启动ServerAgent程序
      • 如果是windows运行startAgent.bat
      • 如果是linux运行startAgent.sh
    • 编写JMeter脚本,配置运行时间
    • 添加PerFmon组件
      • 服务器IP
      • ServerAgent程序端口
      • 待监控的指标

项目实战

项目背景

  • 轻商城项目是一个现在流行的电商项目。我们需要综合评估该项目中各个关键接口的性能,并给出优化建议,以满足项目上线后的性能需要。

项目功能架构

  • 前台商城:购物车、订单、支付、优惠券等
  • 后台管理系统:商品管理、会员管理、商场管理、推广管理等

image-20240114183947730

项目技术架构

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

image-20240114184019425

数据库设计

  • 作用:

    • 熟悉数据库设计结构,便于后期对数据库的性能监控,方便问题定位

    • 构造性能测试数据

image-20240114184045350

轻商城项目搭建

  • 准备工作:安装JDK、MySQL、Nginx

image-20240114184250362

性能测试需求分析

获取需求

  • 客户方提出:

    • 能够提出明确需求的一般是金融、银行、电信、医疗等企业,他们一般对系统的性能要求高,并且对性能也非常了解
  • 根据历史运营数据分析,如:

    • 用户频繁使用的功能模块是哪些

    • 每月、每周、每天的峰值业务量是多少

  • 竞品分析:

    • 对比同类型软件的性能指标结果

提取性能测试点

  • 业务维度提取:

    • 用户频繁使用的业务功能

    • 非常关键的业务功能

    • 特殊交易日或峰值交易的业务功能

    • 核心业务发生重大调整的业务功能

  • 技术维度提取:

    • 资源占用非常高的业务功能

image-20240114185507650

确定性能测试目标

  • 轻商城作为一个新开发的项目,性能测试目标包括:
    • 确定核心业务功能的TPS

    • 对业务流程(多接口组合)进行压测

    • 系统能在实际系统运行压力的情况下,稳定的运行24小时

image-20240114185545414

性能测试计划及方案

  • 掌握如何编写测试计划

  • 测试计划核心内容:

    • 测试背景

    • 测试目的

      • 确定核心业务功能的TPS
      1. 对业务流程(多接口组合)进行压测
      • 系统能在实际系统运行压力的情况下,稳定的运行24小时
    • 测试范围

    • 测试策略

      • 基准测试:先做基准测试,确定估算的标准
      • 负载测试:分别模拟5、10、30、50、100个用户对系统进行负载测试,查看不同并发时系统软件各项指标是否符合需求
      • 稳定性测试:用200用户对系统进行7*24小时的不间断稳定性测试
    • 风险控制

    • 交付清单

    • 进度与分工

image-20240114185735550

image-20240114185739816

性能测试用例设计

image-20240114185810871

性能测试执行

编写测试脚本

  • 常用测试元件:

    • 取样器-HTTP请求
    • 配置元件-HTTP请求默认值
    • 配置元件-用户定义的变量
    • 后置处理器-JSON提取器
    • 断言-响应断言
    • 断言-JSON断言
    • 监听器-察看结果树
    • 监听器-聚合报告
  • JMeter脚本的基本结构:

    • 创建测试用例结构

    • 设置HTTP请求默认值

    • 用户定义的变量

    • 添加监听器-察看结果树

    • 添加监听器-聚合报告

image-20240114185934403

使用JMeter实现测试用例

  • 例如:获取首页数据

  • 操作步骤:

    • 在线程组下,添加取样器‘HTTP请求-获取首页数据’,并填写请求数据

    • 在取样器下,添加‘响应断言’断言响应状态码

    • 在取样器下,添加 ‘JSON断言’ 断言 errno 和 errmsg

    • 发送请求,调试脚本

image-20240114190039654

image-20240114190051340

image-20240114190054753

搭建测试环境

性能测试环境的特点

  • 独占性
  • 尽量保持性能测试环境与真实生产环境的一致性
    • 硬件环境
      • – 包括服务器环境、网络环境等
    • 软件环境
      • – 版本一致性:包括操作系统、数据库、被测应用程序、第三方软件等
      • – 配置一致性:包括操作系统、数据库、被测应用程序、第三方软件等
    • 使用场景的一致性
      • – 基础业务数据的一致性
      • – 业务操作模式的一致性:尽量模拟真实场景下用户的使用情况

构造性能测试数据

  • 目的:压测环境中的数据量尽量与生产环境中数据量一致
  • 方法:为了快速创建大量数据,可以直接操作数据库进行添加
    • 准备插入数据的SQL语句
    • 循环执行SQL语句来插入数据
      • 导包
      • 连接数据库
      • 创建游标
      • 执行SQL语句
      • 关闭游标
      • 关闭连接

案例-构建大量数据

  • 通过编写Python脚本,构造10万条商品记录
  • 操作步骤:
    • 准备插入数据的SQL语句
    • 循环执行SQL语句来插入数据

image-20240114190333572

监控性能测试指标

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

image-20240114190424297

image-20240114190429052

执行性能测试脚本

  • 单台测试机执行:
    • 前提:先保证脚本调试通过之后,才能进入正式压测阶段。
    • 可以选择Windows或者Linux测试机来执行:
  • Windows环境:操作界面化、直观、易上手,但是软件占用机器资源较多,导致资源使用率不高;可支持并发较低。
    • Linux环境:命令行操作,结果查看不太方便,但资源利用率相对较高;可支持较高并发。
    • 分布式执行:
      • 如果单台压测机的并发量不能够满足要求,则可以通过分布式压测来提高并发量。
      • JMeter工具支持分布式压测,即多台机器同时执行同一个脚本,然后统计结果。

性能分析和调优

性能调优的步骤

  1. 确定问题:根据性能监控的数据和性能分析的结果,确定性能存在的问题(要求)

  2. 确定原因:确定了问题之后,对问题进行分析,找出问题产生的原因

  3. 给出解决方案:确定调整目标和解决方案(改服务器参数配置/增加硬件资源配置/修改代码)

  4. 验证问题:按照给出的解决方案,重新进行测试

  5. 分析调优结果:分析出问题的性能指标是否有提升,关注其他指标未下降

  • 注意:性能测试调优并不是一次完成的过程,针对同一个性能问题,上面的五步可能要经过多次循环才能最终完成性能调优的目标(即:测试发现问题-找原因-调整-验证-分析-再测试。。。)

性能瓶颈分析

介绍

  • 在实际的性能测试中,会遇到各种各样的问题,比如TPS压不上去,导致这种现象的原因很多,作为测试人员应配合开发人员进行分析尽快找出瓶颈的所在。

  • 常见的性能瓶颈分析:

    • 服务器资源分析

      • CPU瓶颈:CPU已压满(接近100%),通常其他指标的拐点出现的时刻是否与CPU压满的时刻基本一致
      • 内存瓶颈:内存不足时,操作系统会使用虚拟内存,从虚拟内存读取数据,影响处理速度
      • 磁盘I/O瓶颈:磁盘I/O成为瓶颈时,会出现磁盘I/O繁忙,导致交易执行时在I/O处等待
      • 网络带宽:如果传递的数据包过大,超过了带宽的传输能力,就会造成网络资源竞争,导致TPS上不去
    • JVM瓶颈分析

      • JVM内存:内存申请没有及时释放,造成内存泄漏
    • 数据库瓶颈分析

      • 慢查询
      • 数据库的连接池:设置太小,导致数据库连接出现排队
      • 数据库出现死锁
    • 程序内部实现机制

    • 压测机

      • JMeter单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,也会导致TPS压不上去

CPU瓶颈

  • 每个程序运行都需要占用CPU,那么单CPU的机器是如何同时运行多个程序的?
    • 时间片即CPU分配给各个程序的时间,每个程序被分配一个时间段,称作它的时间片,即该程序允许运行的时间

image-20240114190828401

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

image-20240114190909511

  • 查看CPU使用率的命令:top
  • 测试关注点:
    • 当CPU使用率高时,确定是用户CPU高,还是系统CPU高
    • 如果是用户CPU高,说明某个软件程序的CPU资源占用率高,需要定位代码程序运行的效率
    • 如果是系统CPU高,同步观察是否是其他资源(磁盘IO、内存、网络等)不足

内存和虚拟内存

  • 内存:又称主存储器/物理内存,计算机中所有程序的运行都在内存中进行
  • 虚拟内存:是计算机系统内存管理的一种技术。当计算器内存不足时,可以使用虚拟内存进行补偿
    • 在程序运行时,可以将程序的一部分装入内存,而将其余部分留在外存(磁盘),就可以启动程序执行。
    • 在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。
    • 同时,操作系统将内存中暂时不使用的内容换出到外存上,从而腾出空间存放将要调入内存的信息。
    • 这样,系统好像为用户提供了一个比实际内存大得多的存储器,称为虚拟存储器。

image-20240114191027075

内存瓶颈

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

image-20240114191054446

  • Swap:

    • si: 每秒从交换区写到内存的大小
    • so: 每秒写入交换区的内存大小
  • 测试关注点:

    • 如果si,so 长期不等于0,表示内存不足。(需要大量的从内存和虚拟内存之间读来读去,说明内存盛不开那么多进程,说明内存不足)

磁盘IO瓶颈

  • 磁盘IO瓶颈:影响性能的是磁盘的读写速度(Input和Output速率),不是磁盘大小。
  • 查看磁盘IO使用的命令:iostat -x 1 1

image-20240114191152784

  • Ø %util: 表示一秒中有百分之多少的时间用于 I/O

  • Ø %iowait:CPU等待输入输出完成时间的百分比。

  • 测试关注点:

    • Ø 如果%util接近100%,说明产生的I/O请求太多,I/O系统已经满负荷
    • Ø 如果%iowait的值过高,表示硬盘存在I/O瓶颈

网络瓶颈

  • 网络瓶颈:影响性能的是网络的传输速度,与网络的总带宽进行对比,接近总带宽,说明网络存在瓶颈。
  • 查看网络使用的命令:sar -n DEV 1 2

image-20240114191250352

  • Ø rxkB/s: 每秒接收的数据量(千字节数)

  • Ø txkB/s: 每秒发送的数据量(千字节数)

  • 测试关注点:

    • Ø 将每秒接收的数据量rxkB/s,与网络最大带宽进行对比,如果实际传输速率接近网络最大带宽,说明网络IO有瓶颈

慢查询

  • 慢查询定义:指执行速度低于设置的阀值的SQL语句
  • 作用:帮助定位查询速度较慢的SQL语句,方便更好的优化数据库系统的性能
  • MySQL慢查询参数介绍:
    • Ø slow_query_log: 慢查询日志开启状态[ON:开启,OFF:关闭]
    • Ø slow_query_log_file: 慢查询日志存放位置

image-20240114191347787

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

image-20240114191359002

  • 慢查询开启并配置:
    • Ø 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

image-20240114191452419

数据库连接池

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

image-20240114191544480

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

image-20240114191603450

  • 当客户请求数据库连接时

    • 首先查看连接池中是否有空闲连接,如果存在空闲连接,则将连接分配给客户使用;
    • 如果没有空闲连接,则查看当前所开的连接数是否已经达到最大连接数,如果没达到就重新创建一个连接给请求的客户;
    • 如果达到就按设定的最大等待时间进行等待
    • 如果超出最大等待时间,则抛出异常给客户
  • 测试关注点:

    • Ø MYSQL官网给出了一个设置最大连接数的建议比例:Max_used_connections / max_connections * 100% ≈ 85%,需要关注MYSQL的最大连接数 和 系统运行时数据库已建立连接数的比例
    • Ø 如果已使用连接数与最大连接数比例超过85%,需要增加最大连接数设置,否则会造成连接失败
    • Ø 如果已使用连接数与最大连接数比例小于10%,那显然设置的过大,会造成系统资源的浪费

image-20240114191710714

数据库死锁

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

image-20240114191853722

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

image-20240114191924477

image-20240114191928526

  • kill process_id:如果需要先紧急解决问题,可以先手动杀死死锁的连接

JVM内存

  • JVM内存:Java 虚拟机在执行 Java 程序的过程中所管理的不同的内存数据区域。可简单分为:堆内存和非堆内存

  • Ø 堆内存:主要存放用new关键字创建的对象,所有对象实例以及数组都在堆上分配。 —— 给开发人员使用的(关注)

  • Ø 非堆内存:保存虚拟机自己的静态数据,存放加载的Class类级别静态对象如类、方法等。 —— 给JVM自己使用的

  • JVM堆内存的管理机制(JAVA垃圾回收机制):

    • 年轻代存储“新生对象”,我们新创建的对象存储在年轻代中。
    • 当年轻内存占满后,会触发Minor GC,清理年轻代内存空间。
    • 老年代存储长期存活的对象和大对象。年轻代中存储的对象,经过多次GC后仍然存活的对象会移动到老年代中进行存储。
    • 老年代空间占满后,会触发Full GC。Full GC是清理整个堆空间,包括年轻代和老年代

image-20240114192107721

JVM内存分析

  • 常见的内存问题:

    • l 内存泄漏:
      • Ø 内存泄露 memory leak,是指程序在申请内存后,无法完全释放已申请的内存空间。
      • Ø 一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
    • l 内存溢出:
      • Ø 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out ofmemory
      • Ø memory leak会最终会导致out of memory!
  • 测试关注点:

    • 堆内存使用量持续增长 —— 可能是内存泄漏
    • Full GC比较慢,执行时会停止程序一些事务的处理。因此Full GC频率不能过高(低于10分钟)
    • 如果Full GC之后,堆中仍然无法存储对象,就会出现内存溢出 —— 程序出现crash(崩溃)

image-20240114192232017

JVM内存监控

  • JVM监控 —— 使用本地jvisualvm远程监控服务器:

  • 添加应用程序启动参数,并启动服务

image-20240114192333999

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

image-20240114192412568

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

image-20240114192424829

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

image-20240114192447448

压测机

  • 压测机影响性能测试结果的原因主要是:
    • Ø JMeter单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,也会导致TPS压不上去
  • 压测机资源的监控方法:
    • Ø Windows测试机:自带“任务管理器”
    • Ø Linux测试机:PerfMon组件
  • 解决方案:
    • Ø 采用分布式执行的方法来提高负载量,达到系统性能测试要求的TPS

小结

  • 常见的性能问题主要有哪些方面?
    • 服务器资源分析

      • CPU瓶颈:用户CPU和系统CPU

      • 内存瓶颈:实际内存和虚拟内存

      • 磁盘IO瓶颈:磁盘input和output

      • 网络瓶颈:网络上下行带宽

    • 数据库瓶颈分析

      • 慢查询

      • 数据库连接池

      • 死锁

    • JVM瓶颈分析

      • JVM内存:堆内存和内存回收
    • 程序内部实现机制

    • 压测机

性能调优案例

案例1_获取首页数据

  • 场景描述:

    • Ø 进入首页后,加载首页的相关数据,包括:轮播图、频道、优惠券、团购专区、品牌商直供、新品首发、热卖商品、专题精选等数据
  • 测试结果数据 :

image-20240114192825011

  • 问题分析:
    • CPU已接近100%
    • 一次请求中需要查询很多数据
  • 解决方案:
    • Ø 提升服务器配置
    • Ø 分批次、异步加载首页数据,首页底部的数据(如:新品首发、热卖商品、专题精选等数据)等用户向下滑动页面时再加载

案例2_ 查看商品详情

  • 场景描述:
    • Ø 进入商品详情页面时,加载商品的详细信息
  • 测试结果数据:

image-20240114192932560

  • 问题分析:
    • 网络带宽已跑满
    • 一次请求中返回了全部数据
  • 解决方案:
    • Ø 提升服务器网络带宽
    • Ø 分批次、异步加载商品数据

案例3_搜索商品

  • 场景描述:
    • Ø 进入首页,在搜索框中输入关键字搜索商品
  • 测试结果数据:
    • Ø 搜索关键字“床”时,出现慢查询SQL语句
    • Ø 查看慢查询语句 cat /var/lib/mysql/localhost-slow.log,包含如下SQL语句

image-20240114193046320

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

image-20240114193124974

image-20240114193129203

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

image-20240114193159650

案例4_JVM内存溢出

  • 场景描述:

    • Ø 请求测试接口(/wx/index/oom),模拟内存溢出
  • 测试结果数据:

image-20240114193259108

  • 问题分析:
    • JVM内存占用随着时间的推移占用越来越多,直至内存溢出,系统退出
  • 解决方案:
    • Ø 排查代码存在的问题,及时释放无用的对象

性能测试报告

  • 测试报告核心内容:
    • 测试过程回顾 ——测试目的、测试范围、测试环境、测试使用的工具

    • 测试问题记录及结果分析 —— 性能测试过程中遇到的问题,分析过程和解决方案

    • 测试结论

    • 经验总结和教训

Locust框架

学习目标

  • 掌握如何使用Locust进行接口性能测试

Locust介绍和安装

Locust特点

  • Ø 基于Python的开源负载测试工具
  • Ø 支持多种操作系统
  • Ø 支持二次开发
  • Ø 能够模拟更多用户
  • Ø 基于协程(微线程)的并发

Locust 与 JMeter对比

image-20240114193531978

Locust安装

  • 前提:已安装pycharm、python3.5以上的版本
    • Ø 在线安装: pip install locustio==0.12.2
    • Ø 离线安装
    • Ø Pycharm安装

演示环境接口说明

  1. 登录

  2. 首页

  3. 获取用户信息

  4. 退出

编写Locust测试脚本

测试脚本实现步骤

  • 1、定义任务发送HTTP接口请求。
  • 2、定义任务集定义一个用户行为,包含多个HTTP请求(即具体的任务)。
  • 3、定义Locust类Locust类代表用户,用户会对应具体的用户行为(即任务集)

定义任务

  • locust里发送请求是基于requests实现的,请求方法、参数、响应对象和requests使用方式一样

  • 代码的案例:

1
2
3
4
5
def index(l):
l.client.get("/index")

def login(l):
l.client.post("/login", data={"username": "admin", "password": "123456"})

定义任务集

  • 定义一个用户行为(任务集),包含多个具体的任务。

  • 定义方式:

    • • 定义一个用户行为类,要继承TaskSet类,表示一个任务集
    • • tasks:用来添加任务,它是一个dict类型,key表示任务的方法名,value表示挑选执行的权重,数值越大执行频率越高
    • • on_start:前置方法(前置任务),在所有任务之前调用
    • • on_stop:后置方法(后置任务),当任务集停止时调用
  • 代码案例 :

1
2
3
4
5
6
7
8
9
10
from locust import TaskSet

class UserBehavior(TaskSet):
tasks = {index: 3, profile: 1}

def on_start(self):
login(self)

def on_stop(self):
logout(self)

定义Locust类

  • 定义一个Locust类,这个类代表用户。

  • 定义方式:

    • • 自定义的Locust类继承了HttpLocust类,这个类代表用户
    • • task_set:该属性指向TaskSet类,定义用户的行为
    • • min_wait:用户执行任务之间等待时间的下界,默认值:1000ms
    • • max_wait:用户执行任务之间等待时间的上界,默认值:1000ms
    • • host:被测应用的网址,例如:http://bms-test.itheima.net
    • • weight:用户被选中的概率,权重越大,被选中的机会就越大。默认值:10
  • 代码案例

1
2
3
4
5
6
7
8
from locust import HttpLocust

class WebsiteUser(HttpLocust):
task_set = UserBehavior
min_wait = 2000
max_wait = 3000
host = "http://bms-test.itheima.net/bms"
weight = 10

运行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 开始运行性能测试

image-20240114211451783

Statistics界面

  • 类似于JMeter中的聚合报告:

image-20240114211534714

Charts界面

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

image-20240114211652378

Failures界面

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

image-20240114211711999

Exceptions界面

  • 异常请求的展示界面

image-20240114211736611

Download Data界面

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

image-20240114211805391

image-20240114212202384