💻 性能测试理论 & JMeter使用 🌀

性能测试理论

概述

定义 & 目的
性能测试是通过模拟用户操作,评估系统在不同负载下的表现,确保系统在预期负载下能够稳定运行。
其主要目的是发现系统性能瓶颈,验证系统是否满足性能需求。

重要性
性能测试是软件开发过程中不可或缺的一部分,它可以帮助开发人员和测试人员了解系统的性能瓶颈,从而优化系统性能。
有助于提前发现系统在高负载下的潜在问题,避免上线后出现性能问题,提升用户体验,降低运维成本。

测试指标

  • 响应时间: 从用户发起请求到系统返回响应的时间,通常以毫秒为单位
  • 吞吐量: 系统在单位时间内处理的请求数量,通常以请求/秒为单位
  • 并发用户数: 同时向系统发起请求的用户数量
  • 资料利用率: 系统资源(如CPU、内存、磁盘、网络)的使用情况
  • 错误率: 在测试过程中,系统返回错误响应的比例

工具

选型标准

  • 支持多种协议
  • 易于使用和扩展
  • 提供详细的报告和分析功能
  • 支持分布式测试(可选)

⚠️注意:选型时,一定要考虑投入产出比,不要为了使用工具而使用工具。

常用工具

  • JMeter
  • LoadRunner
  • Gatling
  • Locust

常见术语
相应时间(Response Time):从用户发起请求到系统返回响应的时间,通常以毫秒为单位
吞吐量(Throughput):系统在单位时间内处理的请求数量,通常以请求/秒为单位
并发用户数(Concurrent Users):同时向系统发起请求的用户数量
负载(Load):系统在单位时间内处理的请求数量,通常以请求/秒为单位
压力测试(Stress Test):评估系统在超出正常负载情况下的表现。
稳定性测试(Stability Test):评估系统在长时间运行下的稳定性。
容量(Capacity):系统能够支持的最大工作负载(如最大用户数或数据量)
延迟(Latency):请求从发出到开始处理之间的时间,通常不包括处理时间
每秒事务数(Transaction Per Second, TPS):系统每秒能够完成的事务数量
资源利用率 (Resource Utilization):系统运行时对硬件资源的占用情况,如 CPU 使用率、内存使用率、磁盘I/O等
基准测试(Benchmark Test):评估系统在特定条件下的性能基准/在标准条件下测试系统性能,建立性能基线
可扩展性(Scalability):系统在增加负载(如用户或数据)时,通过增加资源(如服务器)保持性能的能力
瓶颈(Bottleneck):系统性能受限的环节,可能是硬件、软件或网络的某个部分

流程

① 需求分析: 明确性能测试的目标和范围,确定性能指标和测试场景
② 测试计划: 制定详细的测试计划,包括测试环境、测试工具、测试数据、测试时间等
③ 测试设计: 设计测试场景和测试用例,确定并发用户数、负载模式等
④ 测试执行: 按照测试计划执行测试,监控系统性能和资源使用情况
⑤ 结果分析(+评审): 分析测试结果,识别性能瓶颈,评估系统是否满足性能需求
⑥ 报告编写: 编写性能测试报告,记录测试过程、结果分析和改进建议

性能测试通过标准:包括服务端性能、前端性能和用户体验性能

  • 服务端性能:
    • 超时概率
    • 错误概率
    • TPS
    • CPU利用率
    • 响应时间
    • Load
    • JVM内存使用率
    • Full GC频率(小于半小时一次)
  • 前端性能:
    • YSlow评定
  • 用户体验性能

策略/类型

负载测试:评估系统在正常和峰值负载下的表现。
压力测试:评估系统在超出正常负载情况下的表现。
稳定性测试:评估系统在长时间运行下的稳定性。
容量测试:评估系统在最大负载下的表现。
基准测试:评估系统在特定条件下的性能基准。

优化

瓶颈识别: 通过分析测试结果,识别系统性能瓶颈,如CPU、内存、磁盘、网络等
优化策略: 根据瓶颈识别结果,制定优化策略,如优化SQL、优化代码、优化配置等
优化效果验证: 通过测试验证优化效果,确保优化后的系统性能满足需求

JMeter

概述

Apache JMeter 是一个开源的性能测试工具,主要用于测试 Web 应用程序的性能。
它支持多种协议,如 HTTP、HTTPS、FTP、JDBC 等,并且可以通过插件扩展功能。

安装
官网 https://jmeter.apache.org/ 下载,打开bin目录下的jmeter即可打开,如下: 安装

➜  apache-jmeter-5.6.3 $ tree -L 1
.
├── LICENSE		# 许可证文件
├── NOTICE		# 通知文件
├── README.md		# 说明文件
├── bin			# 可执行文件 和 配置文件,是jmeter的核心目录
├── docs		# 文档和示例文件
├── extras		# 额外的工具和插件
├── lib			# 库文件(JAR文件)
├── licenses		# 许可证文件
└── printable_docs	# 可打印的文档

运行原理线程方式运行(区别与LoadRunner可以选择以进程方式还是以线程方式) 运行在JVM上(所以需要先安装JDK) 采用事件驱动模型

核心组件

JMeter运行顺序:

  1. 配置元件 Config Element
  2. 前置处理器 Pre Processor
  3. 定时器 Timer
  4. 取样器 Sampler
  5. 后置处理器 Post Processor
  6. 断言 Assertion
  7. 监听器 Listener

测试计划 Test Plan

测试计划是 JMeter 测试的顶层容器,包含所有测试元素。它是测试的起点,可以添加线程组、配置元件、监听器等。

线程组 Thread Group

线程组用于模拟用户并发执行的线程集合。可以设置线程数、循环次数、启动时间等参数。

setUp Thread Group:用于设置测试开始前的准备工作,如初始化数据、登录等。
tearDown Thread Group:用于设置测试结束后的清理工作,如清理数据、退出登录等。

取样器/采样器 Sampler

取样器用于发送请求并接收响应。常见的取样器包括 HTTP 请求、FTP 请求、JDBC 请求等,基本涵盖了我们常见的各种协议。

路径:测试计划 → 线程组 → Sampler

Flow Control Action
HTTP Request
Debug Sampler
JSR223 Sampler
AJP/1.3 Sampler
Access Log Sampler
BeanShell Sampler
Bolt Request
FTP Request
GraphQL HTTP Request
JDBC Request
JMS Point-to-Point
JMS Publisher
JMS Subscriber
JUnit Request
Java Request
LDAP Extended Request
LDAP Request
Mail Reader Sampler
OS Process Sampler
SMTP Sampler
TCP Sampler

监听器 Listener

监听器用于查看和分析测试结果。常见的监听器包括查看结果树、聚合报告、图形结果等。

路径:测试计划 → 监听器

View Results Tree
Summary Report

以表格形式显示取样器结果。
注意:不同取样器要有不同的名字,如果名字相同,在Summary Report中会统计到同一行。 jmeter-listener-summary-report

  • Write results to a file:将结果写入文件
    • Filename: 文件名(可以点击右侧的‘configure’按钮,选择字段)
  • Result Info: 结果信息 → 是表格
    • Label: 取样器名称(事务名)
    • Samples: 取样器运行次数
    • Average: 平均响应时间
    • Min: 最小响应时间
    • Max: 最大响应时间
    • Std. Dev: 响应时间的标准偏差
    • Error %: 错误率
    • Throughput: 吞吐量,即TPS
    • Received KB/sec: 接收速率
    • Sent KB/sec: 发送速率
    • Average Bytes: 平均字节数
Aggregate Report

和Summary Report类似,但是可以设置多个聚合报告,每个聚合报告可以设置不同的字段。 jmeter-listener-aggregate-report

  • Write results to a file:将结果写入文件
    • Filename: 文件名(可以点击右侧的‘configure’按钮,选择字段)
  • Result Info: 结果信息 → 是表格
    • Label: 取样器名称(事务名)
    • Samples: 取样器运行次数
    • Average: 平均响应时间
    • Median: 中位数
    • 90% Line: 90%的请求的响应时间
    • 95% Line: 95%的请求的响应时间
    • 99% Line: 99%的请求的响应时间
    • Min: 最小响应时间
    • Max: 最大响应时间
    • Error %: 错误率
    • Throughput: 吞吐量,即TPS
    • Received KB/sec: 接收速率
    • Sent KB/sec: 发送速率
Backend Listener
Aggregate Graph
Assertion Results
Comparison Assertion Visualizer
Generate Summary Results
JSR223 Listener
Mailer Visualizer
Response Time Graph
Save Responses to a file
Simple Data Writer
View Results in Table
BeanShell Listener

配置元件 Config Element

配置元件用于配置测试环境,如 HTTP 请求默认值、CSV 数据文件设置等。

路径:测试计划 → 配置元件

CSV Data Set Config

可以从指定的文件(一般是文本文件)中一行一行的提取文本内容,根据分隔符拆解这一行内容并把内容与变量名对应上,然后这些变量即可供取样器适应了。 jmeter-config-element-csv-data-set-confg

  • Filename: 文件路径(可以是绝对路径,也可以是相对路径)
  • File Encoding: 文件编码(默认是UTF-8)
  • Variable Names: 变量名(变量名之间用逗号分隔)
  • Ignore First Line: 忽略第一行
  • Delimiters: 分隔符(默认是逗号,也可以使用tab分隔\t
  • Allow Quoted Data: 允许引号数据
  • Recycle on EOF: 到达文件末尾时循环读取
  • Stop Thread on EOF: 到达文件末尾时停止线程
  • Sharing mode: 共享模式(默认是所有线程共享,也可以选择当前线程私有)
HTTP Header Manager
HTTP Cache Manager
HTTP Request Defaults

测试过程中,我们的额服务器名称或IP是不变的,端口也是不变的,如果每次都要写一遍,工作量会很大,因此,jmeter提供了HTTP Request Defaults组件,可以设置默认的服务器名称或IP、端口等。 jmeter-config-element-http-request-defaults

  • Web Server:
    • Protocol: 协议(http/https)
    • Server Name or IP: 服务器名称或IP
    • Port Number: 端口
  • HTTP Request:
    • Method: 方法(GET/POST..)
    • Path: 路径
    • Content Encoding: 内容编码
    • Redirect Automatically: 自动重定向
    • Follow Redirects: 是否跟随重定向
    • Use KeepAlive: 是否使用长连接
    • Use multipart/form-data: 是否使用multipart/form-data格式
    • Browser-compatible headers: 是否使用浏览器兼容的头部
  • Parameters: 请求参数
  • Body Data: 请求体
  • File Upload: 文件上传
Bolt Connection Configuration
Counter
DNS Cache Manager
FTP Request Defaults
HTTP Authorization Manager
JDBC Connection Configuration
Java Request Defaults
Keystore Configuration
LDAP Request Defaults
Login Config Element
Random Variable
Simple Config Element
TCP Sampler Config
User Defined Variables

前置处理器 Pre Processor

前置处理器在取样器执行之前执行,用于准备测试数据或修改请求。

路径:测试计划 → 前置处理器

JSR223 PreProcessor
User Parameters
HTTP URL Re-writer Modifier
JDBC PreProcessor
RegEx User Parameters
Sample Timeout
BeanShell PreProcessor

后置处理器 Post Processor

后置处理器在取样器执行之后执行,用于处理响应数据或修改请求。

路径:测试计划 → 后置处理器

CSS Selector Extractor
JSON Extractor
JSON JMESPath Extractor
Boundary Extractor
Regular Expression Extractor
JSR223 PostProcessor
Debug PostProcessor
JDBC PostProcessor
Result Status Action Handler
XPath Extractor
XPath2 Extractor
BeanShell PostProcessor

断言 Assertion

断言用于验证测试结果是否符合预期。常见的断言包括响应码断言、响应时间断言、正则表达式断言等。

Response Assertion

响应断言:对服务器的响应数据进行规则匹配。 jmeter-assertion-response-assertion

  • Apply to: 匹配范围
    • Main sample and sub-samples: 主取样器和子取样器
    • Main sample only: 主取样器
    • Sub-samplers only: 子取样器
    • JMeter Variable Name to user: 支持对JMeter变量值进行匹配
  • Field to Test:
    • Text Response: 响应文本
    • Response Code: 响应码
    • Response Message: 响应消息
    • Response Headers: 响应头
    • Request Headers: 请求头
    • URL Sampled: 采样URL
    • Document(text): 文档内容(文本)
    • Ignore Status: 忽略状态(若一个请求有多个响应断言,其中的响应断言若选中此项,则会忽略此响应结果)
    • Request Data: 请求数据
  • Pattern Matching Rules: 匹配规则
    • Contains: 包含
    • Matches: 匹配
    • Equals: 等于
    • Substring: 子字符串
    • Not: 不
    • Or: 或
  • Pattern to Test: 测试模式
  • Custom failure message: 自定义失败消息
JSON Assertion
Size Assertion
JSR223 Assertion
XPath Assertion
Comparison Assertion
Duration Assertion
HTML Assertion
JSON JMESPath Assertion
MD5Hex Assertion
SMIME Assertion
XML Assertion
XML Schema Assertion
XPath Assertion
BeanShell Assertion

逻辑控制器 Logic Controller

逻辑控制器用于对元件的执行逻辑进行控制,如条件控制、循环控制等。
除了仅一次控制器外,其他控制器下可以嵌套其他控制器。

If Controller
Transaction Controller

事务控制器。 jmeter-logic-controller-transaction-controller

  • Generate parent sample: 生成父取样器
    • 如果事务控制器中有多个取样器/请求,勾选之后,在‘察看结果树’中不仅可以看到事务控制器,还能看到每个取样器/请求
    • 事务控制器的事务是否成功取决于所有子取样器/请求是否成功,其中任何一个取样器/请求失败,事务控制器的事务都会失败
  • Include duration of timer and pre-post processors: 是否包含定时器和前置后置处理器的持续时间
Loop Controller
Critical Section Controller
ForEach Controller - 循环控制器

定义一个循环规则。 jmeter-logic-controller-foreach-controller

Input variable prefix: 输入变量前缀 Start index for loop(exclusive): 循环开始索引(不包含) End index for loop(exclusive): 循环结束索引(不包含) Output variable name: 输出变量名 Add ‘_’ before number? : 是否在变量名前添加下划线

Include Controller - 包含控制器

允许将外部的测试计划片段(.jmx 文件)包含到当前的测试计划中m,实现测试脚本的模块化和复用,避免重复编写相同的测试逻辑。(可以理解为编程语言中的函数以及函数调用) 典型使用场景:把登录、退出等通用操作保存为.jmx文件。 jmeter-logic-controller-include-controller

  • Include Test Plan:
    • Filename: 文件名(必填字段)

注意:被导入的测试计划中,不能有线程组,因为:线程组是测试计划的顶层元素,只能在测试计划的根节点下直接添加。
Include Controller只能加载非线程组的测试片段(例如:逻辑控制器、取样器、配置元件等)

补充:Include Controller vs Module Controller

特性 Include Controller Module Controller
数据来源 外部.jmx文件 当前测试计划中的模块
可复用性 跨测试计划复用 仅限当前测试计划中复用
线程组支持 不支持 不支持
动态加载 是(运行时加载) 否(静态引用)
适用场景 跨项目模块化 同一测试计划内的模块化
Interleave Controller
Once Only Controller
Random Controller
Random Order Controller
Recording Controller
Runtime Controller

用来控制子元件的执行时长,单位是秒(s)。当到达设定时间后,控制器会停止执行其子元件。
适用于:需要按时间维度控制测试步骤的场景(如持续运行某操作5分钟) jmeter-logic-controller-runtime-controller

  • Runtime(seconds): 执行时长(默认为1,去掉1则默认为0,此时不执行其节点下的元件)

注意: 1.若子元件是事务控制器或包含多个步骤,超时后会立即停止,不会等待当前步骤完成。 2.子元件内的定时器(如Constant Timer)会增加每次迭代的总时间,需要计算总时间时考虑。 3.在分布式测试中,Runtime Controller只对当前从机(Slave)生效,主机会忽略此控制器。

补充:Runtime Controller vs Loop Controller vs While Controller

控制器 控制维度 终止条件 典型场景
Runtime Controller 时间 总运行时间到达设定值 稳定性测试、超时控制
Loop Controller 次数 循环次数到达设定值 固定次数的重复操作
While Controller 条件 条件为真 动态条件控制(如响应内容)
Simple Controller - 简单控制器

是JMeter中最基本的逻辑控制器,它的主要作用是组织和管理测试计划中的其他元件(如取样器、定时器、断言等)。
Simple Controller 本身不会对测试逻辑产生任何影响,它仅仅是一个容器,用于将相关的测试元件分组,使测试计划更加清晰和易于管理。 jmeter-logic-controller-simple-controller

Throughput Controller
Module Controller
Switch Controller

定时器 Timer

定时器用于控制取样器的执行时机,常见的定时器包括固定定时器、随机定时器、高斯定时器等。

Constant Timer
Uniform Random Timer
Precise Throughput Timer
Constant Throughput Timer
Gaussian Random Timer
JSR223 Random Timer
Poisson Random Timer
Synchronizing Timer

同步定时器:用来保证取样器在同一时刻向服务器发起负载。
考虑到线程运行的时间快慢与场景的需求,也提供了同步线程数量的设置。 jmeter-timer-synchronizing-timer

  • Grouping:
    • Number of Simulated Users to Group by: 同步的线程数量(测试过程中,每一个线程的运行时间可能不一样,想要让所有线程集合在一起可能会等待较长时间,此时可以先让一部分集合完毕的线程运行起来)
    • Timeout in milliseconds: 超时时间(单位:毫秒)
BeanShell Timer

测试片段 Test Fragment

测试片段用于将多个取样器组合成一个测试片段,方便管理。(可以理解为函数)

测试执行与结果分析

执行测试

GUI运行

本地运行

直接点击UI页面的运行按钮即可。

远程运行

在配置文件jmeter.properties中,添加remote_hosts字段:

remote_hosts=192.168.1.100,192.168.1.101,192.168.1.102

注意:远程运行的脚本,如果有参数化文件,脚本有依赖包时,需要手工把这些参数文件、依赖包拷贝到远程机器上。(JMeter不灵活的地方)

非GUI运行/命令行运行

运行参数:

  • -n:非GUI模式运行
  • -t:测试脚本(可以是相对路径,也可以是绝对路径)
  • -h: 查看帮助
  • -v: 查看版本
  • -p:指定配置文件
  • -l:结果文件(可以是相对路径,也可以是绝对路径)
  • -s: 以服务器方式运行(也就是远程方式,启动agent)
  • -H:设置代理,一般填写代理IP
  • -P: 设置代理端口
  • -u:设置用户名
  • -a: 代理口令
  • -J: 设置JVM参数(等价与在jmeter.properties中添加参数)
  • -G: 设置全局参数(等价于在Global.properties中添加参数,线程间可以共享)
  • -D: 设置系统参数(等价与在system.properties中添加参数)
  • -S: 加载系统属性文件(可以通过此参数指定加载一个系统属性文件,可以用户自定义)
  • -L: 设置日志级别
  • -r: 开启远程负载机(非GUI模式下,需要开启)

运行命令:

# ①
$ java -jar %JMETER_HOME%/bin/jmeter.jar -n -t %JMETER_HOME%/scripts/test.jmx -r -l result.jtl

# ②
$ %JMETER_HOME%/bin/jmeter -n -t %JMETER_HOME%/scripts/test.jmx -r -l %JMETER_HOME%/result/results.jtl

运行:性能参数配置

使用JMeter进行性能测试时,GUI模式可能会占用较多的系统资源,尤其是在处理大量并发请求时。为了优化JMeter在Java虚拟机(JVM)上的运行性能,可以通过调整JVM参数来提高其运行效率和稳定性。

堆内存设置

  • -Xms:设置JVM初始堆内存大小
  • -Xmx:设置JVM最大堆内存大小
-Xms512m -Xmx2048m

新生代内存设置

  • -XX:NewSize: 设置新生代的初始大小。
  • -XX:MaxNewSize: 设置新生代的最大大小。
-XX:NewSize=256m -XX:MaxNewSize=512m

垃圾回收器设置

  • -XX:+UseG1GC:使用G1垃圾回收器,适用于大内存和多核处理器
  • -XX:+UseConcMarkSweepGC:启用CMS垃圾回收器,适用于低延迟应用
-XX:+UseG1GC -XX:+UseConcMarkSweepGC

线程栈大小

  • -Xss:设置每个线程的栈大小(如果测试中有大量线程,可以适当减少栈大小以节省内存)
-Xss256k

元空间大小
[Java 虚拟机(JVM)中用于存储类元数据(Class Metadata)的内存区域。它是从 Java 8 开始引入的,取代了之前的 永久代(PermGen)]

  • -XX:MetaspaceSize:设置元空间的初始大小
  • -XX:MaxMetaspaceSize:设置元空间的最大大小
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m

监控测试过程

主要任务是:获取运行状态、收集测试结果,包括:事务响应时间、吞吐量、错误率及硬件性能(CPU、内存、磁盘I/O、网络带宽)、JVM使用情况、数据库性能状态(连接数、查询性能、锁等待时间)等。

在JMeter中,监听器可以统计:吞吐量、响应时间等指标。
硬件性能、数据库性能等指标需要通过其他工具监控,如:Prometheus、Grafana、Zabbix等。

监控工具

  • JMeter内置监控器(参见上方Listener部分)
    • 查看结果树:查看每个请求的详细结果,包括请求和响应数据。
    • 聚合报告:汇总测试结果,包括平均响应时间、吞吐量、错误率等。
    • 图形化结果:生成实时图表,显示线程数、响应时间、吞吐量等指标。
  • JMeter插件
    • PerfMon Metrics Collector:监控服务器的 CPU、内存、磁盘 I/O 等资源使用情况。
    • Prometheus Listener:将 JMeter 测试数据导出到 Prometheus,结合 Grafana 进行可视化监控。
    • SSHMon Samples Collector:通过 SSH 连接服务器,使用 sar 命令监控系统资源。
  • 第三方监控工具
    • Grafana + InfluxDB:将 JMeter 测试数据存储到 InfluxDB,并通过 Grafana 进行可视化展示。
    • Prometheus + Grafana:通过 Prometheus 采集 JMeter 数据,结合 Grafana 进行监控。
    • ServerAgent:部署在服务器上,实时监控服务器资源使用情况。

分析测试结果

生成测试报告

JMeter最佳实践

脚本优化

瓶颈识别

环境管理

持续集成与自动化

其他

函数助手

点击菜单栏中的函数助手,可以查看所有可用的函数,并选择对应的函数进行使用。如下图: jmeter-function-helper

录制 badboy

插件 plugin

Reference

1.JMeter官网
2.JMeter官网Demo
3.《全栈性能测试修炼宝典 JMeter实战》