- 性能测试分析负载、压力、稳定性和峰值,以确定系统的真正极限。
- Apache JMeter 允许您使用线程组、HTTP 采样器、计时器和断言来模拟虚拟用户。
- 配置 JVM、日志记录和监听器是运行可靠测试和正确调试测试的关键。
- PerfMon 等插件扩展了 JMeter 的功能,使您可以将服务器指标与负载结果关联起来。

如果你从事软件质量管理工作,迟早会遇到需要衡量应用程序在负载下实际性能的情况。仅仅在只有你一个人点击时功能响应良好是不够的:重要的是要了解当几十甚至几百个用户同时连接、发送请求、浏览网页并将服务器推向极限时会发生什么。
在这样的背景下,Apache JMeter 已成为领先的性能测试工具之一。它免费、高度灵活,虽然界面乍看之下可能有些复杂,但一旦掌握了四个关键概念,一切都会迎刃而解。在本教程中,我将详细解释什么是性能测试,它在更广泛的测试领域中扮演着怎样的角色,以及如何在 JMeter 中逐步设置你的第一个测试计划,面面俱到。
什么是性能测试?为什么性能测试很重要?
在测试领域,我们通常区分功能测试和非功能测试。功能测试侧重于验证系统功能是否按预期运行:例如业务逻辑、用户流程、规则等等。而非功能测试则侧重于与逻辑没有直接关系的方面:例如界面外观、内容质量、图像使用、视觉效果、安全性,尤其是性能。
谈到性能,我们关注的是系统在不同负载水平下的运行情况。我们想知道应用程序的响应速度是否快,能否应对用户流量的增长,能否长期保持稳定,或者是否会在突发高峰下崩溃。性能测试旨在产品正式上线前,检测出瓶颈、容量问题以及系统的真正极限。
在项目层面,这些测试的目标是回答一个非常具体的问题:应用程序是否已准备好在预期用户量下投入生产环境?为此,需要评估响应时间、最大容量、稳定性、资源消耗以及系统在极端情况下的行为等特性。
为了涵盖所有这些场景,我们设计了几种相互补充的性能测试。每种测试都旨在模拟不同的情况,并获取有关系统响应的具体信息。
性能测试类型:负载测试、应力测试、稳定性测试和峰值测试
性能测试涵盖多种测试模式,每种模式都有其明确的目的。在制定性能测试策略时,通常会结合负载测试、压力测试、稳定性测试和峰值测试,以全面了解系统行为。
负载测试可能是最常见的测试类型。它的目的是评估应用程序在代表实际使用情况的负载下的性能,例如,平均每日流量或预计高峰时段的流量。实际上,它会模拟多个虚拟用户同时访问系统,执行我们最关心的关键操作(登录、搜索、购买等)。这使我们能够了解例如 20 个或 200 个用户同时使用平台时会发生什么情况。
在这种情况下,重要的是施加系统典型的负载水平,观察响应时间、错误率和资源消耗,并识别潜在的瓶颈。这是一种非常直接的方法,可以了解应用程序在接近真实生产环境的条件下如何运行。
压力测试更进一步。它并非将负载控制在预期范围内,而是将系统推至极限,甚至超越其极限。其目的是分析流量激增时系统的反应:服务性能如何下降,是否出现大规模错误,系统是否彻底崩溃,以及系统是否具备可控的降级机制。压力测试与其说是用于预测日常行为,不如说是用于研究系统在极端场景下的性能。
稳定性测试,也称为耐久性测试或浸泡测试,侧重于在较大的负载下(但低于压力负载)长时间观察系统行为。其目的是维持数小时(甚至数天)的稳定负载,以检验系统是否能够保持稳定,避免出现内存泄漏或性能逐渐下降的情况。这是发现那些仅在长期运行中才会出现的问题的理想方法。
最后,还有峰值测试。这种测试的重点在于让系统在极短时间内承受突然而剧烈的负载增长,以分析其对流量快速波动的响应。这种场景常见于一次性营销活动、病毒式传播的新闻报道或特定产品的发布,在这些情况下,流量会突然激增,然后又迅速下降。
Apache JMeter 的基本安装
Apache JMeter 是一个 Java 工具,因此首要条件是您的计算机上已正确安装 JRE 或 JDK,并且 JAVA_HOME 环境变量指向该安装目录。否则,JMeter 将无法启动。
安装过程非常简单。只需从 Apache JMeter 官方网站下载最新稳定版本,然后将 ZIP 或 TAR 文件解压到您想要安装该工具的目录即可。无需传统的安装程序:解压后,您会在类似 apache-jmeter-XY 的路径中找到典型的 JMeter 文件夹结构,其中 XY 是版本号。
在该文件夹内,您会看到几个子目录:bin、lib、docs、extras、lib/ext、lib/junit、licenses 和 printable_docs。请勿更改这些子目录的名称,但如果您觉得重命名主文件夹更方便,则可以这样做。关键是要保持 JMeter 所期望的内部结构。
要在 Windows 系统上以图形模式 (GUI) 运行该工具,您必须运行位于 bin 文件夹中的 jmeter.bat 文件。在 Unix 或 Linux 系统上,请使用 jmeter 脚本。几秒钟后,JMeter 图形界面应该会出现。值得注意的是,GUI 模式主要用于创建和编辑测试计划,而对于运行大型性能测试,始终建议使用命令行模式(CLI 或非 GUI),以节省资源,尤其是在现代虚拟机上。
bin 文件夹还包含其他一些有用的 Windows 专用脚本:例如 jmeterw.cmd(用于在不打开 Windows 控制台的情况下启动 JMeter)、jmeter-n.cmd(用于通过拖放 JMX 文件在 CLI 模式下运行测试)、jmeter-nr.cmd(功能相同,但运行在分布式模式下)、jmeter-t.cmd(用于在图形模式下打开 JMX 脚本)、jmeter-server.bat(用于在服务器模式下启动 JMeter),以及 shutdown.cmd 和 stoptest.cmd,分别用于优雅地或突然地停止 CLI 执行。这些脚本在处理分布式环境以及需要创建虚拟网络进行测试时非常有用。
在 Unix 环境中,存在类似的脚本:jmeter(默认的图形用户界面,包含一些 JVM 设置)、jmeter-server(用于服务器模式)、mirror-server.sh(用于镜像服务器)以及 shutdown.sh 和 stoptest.sh(用于停止命令行执行)。在这些系统中,通常需要配置 JAVA_HOME、JRE_HOME 或 HEAP 等环境变量来调整 JVM 的行为。
JVM 配置和环境变量
JMeter 允许用户对其运行所使用的Java 虚拟机 (JVM) 选项进行高度精细的自定义。这在运行高强度负载测试并需要控制内存大小、垃圾回收或接口语言等参数时至关重要。
在 Windows 系统中,集中管理这些设置的便捷方法是在 bin 文件夹中创建一个名为 setenv.bat 的文件。该脚本会在使用 jmeter.bat 启动 JMeter 时自动运行,并允许您定义诸如 JVM_ARGS、HEAP、GC_ALGO、JMETER_LANGUAGE、JMETER_HOME、JMETER_BIN、JM_LAUNCH 和 JMETER_COMPLETE_ARGS 等变量。
例如,您可以在 setenv.bat 文件中定义一行类似 ` set JVM_ARGS=-Xms1024m -Xmx1024m -Dpropname=value` 的命令,以配置 Java 的最小和最大内存大小以及其他属性。当您从命令行调用 JMeter 时,例如使用 `jmeter -t test.jmx` 命令,这些参数将生效。
HEAP 和 GC_ALGO 变量用于设置 JVM 的内存分配和垃圾回收算法。默认情况下,JMeter 通常使用类似 -Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m 的参数进行内存分配,并使用类似 -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:G1ReservePercent=20 的选项来指定 G1GC 垃圾回收器。定义 JMETER_COMPLETE_ARGS 参数则指定仅应用 JVM_ARGS 和 JMETER_OPTS 参数,而忽略 HEAP 和 GC_ALGO 等默认配置。
在 Unix 或 Linux 系统中,等效机制是 setenv.sh 文件,它也位于 bin 文件夹中。该脚本在 JMeter 启动时生成,允许您导出诸如HEAP、GC_ALGO、JMETER_LANGUAGE、JMETER_OPTS、JAVA_HOME、JRE_HOME 或 JVM_ARGS之类的变量。例如,您可以定义 `export HEAP="-Xms1G -Xmx1G -XX:MaxMetaspaceSize=192m"` 来根据需要调整内存分配,或者定义 `export JMETER_LANGUAGE=""` 来让操作系统自动检测语言。
正确配置这些变量对于运行高要求测试至关重要,因为它可以防止 JMeter 因内存不足或资源匮乏而出现异常行为。此外,将配置集中在 setenv.bat 或 setenv.sh 文件中,可以更轻松地在不同的机器上复现环境。
JMeter中的日志管理和日志级别
JMeter 每次在执行过程中检测到错误时,都会将一条消息写入其日志文件。默认情况下,该文件名为jmeter.log,并创建在工具启动的目录中,不过可以通过 Log4j2 配置或命令行参数更改此名称。
日志配置通过 log4j2.xml 文件完成,该文件定义了 appender 和 logger。一个典型的例子包括一个 File appender,用于生成主日志文件 jmeter.log,以及另一个专门用于图形界面日志查看器 (GuiLogEvent) 的 appender。通常,这两个 appender 的引用都会添加到根 logger 中,默认日志级别为 info。
如果您想修改特定类别(例如 Apache HttpClient)的详细程度,可以在启动 JMeter 之前,向 Loggers 部分添加类似 ` <Logger name="org.apache.http" level="debug" />`的元素。这样,运行测试时,您将获得该特定库的详细调试信息。
另一种方法是使用 `-L` 选项直接从命令行更改日志级别。例如,`jmeter -Ljmeter.engine=DEBUG` 或 `jmeter -Lorg.apache.jmeter.engine=DEBUG` 允许您将 `jmeter.engine` 类别的日志级别设置为 DEBUG。您还可以使用类似 `jmeter -Lcom.example.foo=DEBUG` 或 `jmeter -LDEBUG` 的命令,通过单个命令修改多个日志级别。
自 3.2 版本起,JMeter 使用 SLF4j 作为其日志 API,Log4j 2 作为其日志框架,导致日志级别略有变化。此前,日志级别包括 DEBUG、INFO、WARN、ERROR、FATAL_ERROR 和 NONE。现在,DEBUG、INFO、WARN 和 ERROR 仍然保留,但 FATAL_ERROR 被视为 ERROR,并且新增了 TRACE 级别,提供比 DEBUG 更详细的信息。此外,还有一个 OFF 级别用于禁用日志记录。
日志文件不仅记录错误,还记录相关的测试事件:JMeter 版本、JMX 文件加载、执行引擎启动、线程启动、测试完成等。当您需要调查运行失败的原因或了解复杂场景中的事件顺序时,这些信息非常宝贵。
您在 JMeter 中的第一个测试计划:基本概念
以图形模式启动 JMeter 时,首先会看到一个包含两个主要区域的窗口。左侧是树状视图,显示构成测试计划的所有元素;右侧是所选元素的配置面板。所有测试逻辑都将围绕该测试计划展开。
测试计划充当根容器,按层次结构对运行测试所需的各种组件进行分组:线程组、采样器、计时器、断言、监听器等。树中的每个节点都在右侧面板中进行配置,JMeter 会遍历此结构来运行已定义的场景。
在测试计划中,首先要添加的元素之一是线程组。该组件代表一组虚拟用户(线程),JMeter 将针对您要测试的服务启动这些线程。您可以将它们想象成一种机器人,模拟真实用户的行为,并发发送请求。
要添加线程组,请右键单击测试计划,然后依次选择“添加”>“线程(用户)”>“线程组”。添加完成后,您将在右侧面板中看到其属性。您可以在此处定义关键参数,例如线程(用户)数量、启动周期和循环次数。
“线程数(用户数)”字段指示您希望在此测试中模拟多少个虚拟用户。如果您输入 100,JMeter 将创建 100 个线程。“启动周期(秒)”决定了启动所有这些线程所需的时间。例如,如果您指定线程数为 100,启动周期为 60 秒,JMeter 将以大约每秒 100/60 ≈ 1,67 个用户的速度启动,直到达到 100 个用户。这样,负载不会突然飙升,而是逐渐增加。
循环次数参数指示每个线程将执行线程组中包含的采样器和元素序列的次数。您可以设置特定的迭代次数,或者选择无限循环选项(永久循环),以便该组持续发送请求,直到您手动停止测试。
“采样器错误后要执行的操作”代码块定义了当采样器中发生错误时 JMeter 应该执行的操作。您有几个选项:`CONTINUE`(即使出现错误也继续执行)、`START NEXT THREAD LOOP`(如果出现错误,则继续执行下一个线程循环)、`STOP THREAD`(仅停止当前线程,不执行后续循环)以及 `STOP TEST` 或 `STOP TEST NOW`,它们会停止整个测试。`STOP TEST` 和 `STOP TEST NOW` 的区别在于后者更激进;它会立即中断测试,而不会等待当前线程完成。
添加HTTP采样器和计时器
线程组配置完成后,下一步是告诉 JMeter 要发送哪种类型的请求。这时就需要用到采样器了。采样器负责向被测系统发送请求并收集响应。对于 Web 应用程序,通常使用 HTTP 请求采样器。
要添加 HTTP 请求采样器,请右键单击线程组,然后选择“添加”>“采样器”>“HTTP 请求”。这将在树中添加一个新节点,您可以在其中配置要连接的服务器、端口、协议、路径以及其他附加参数,例如方法(GET、POST 等)或表单数据。
假设您想测试一个示例网站(例如 www.blazedemo.com)首页的加载情况。在“服务器名称或 IP 地址”字段中,您需要输入www.blazedemo.com。由于您访问的是首页,因此可以根据您的配置,将“路径”字段留空(例如使用斜杠 /),甚至留空。之后,每个虚拟用户都会在其工作流程中运行此示例程序。
为了使测试更贴近实际应用,建议在请求之间引入等待时间,模拟用户实际使用应用程序的情况。在 JMeter 中,这可以通过定时器来实现。定时器会在采样器执行之间引入额外的延迟,防止所有采样器立即触发,从而避免不自然的执行。
最简单的定时器是常量定时器。要将其添加到 HTTP 采样器,请右键单击采样器,然后选择“添加”>“定时器”>“常量定时器”。在其设置中,您可以指定一个以毫秒为单位的延迟值。此时间将应用于采样器的每次执行;也就是说,每个线程在发送请求之前都会等待此延迟,这有助于更均匀地分配流量。
另一个非常有用的定时器是均匀随机定时器。它会添加一个由固定部分和随机部分组成的延迟。要使用它,请选择“添加”>“定时器”>“均匀随机定时器”。在其面板中,您会看到“随机延迟最大值”(随机部分的最大值)和“固定延迟偏移量”(固定部分)字段。例如,如果您将“随机延迟最大值”设置为 100 毫秒,并将“偏移量”设置为 0,则每个线程在发送请求之前都会有 0 到 100 毫秒之间的随机延迟。这会在虚拟用户之间引入差异,更接近于模拟人类行为。
使用断言验证响应
发送请求没问题,但如果我们不检查服务器返回的内容,就可能误以为一切正常,而实际上却发生了错误。这就是断言的作用所在:它允许我们验证响应是否满足特定条件。
要添加响应断言,请右键单击要验证的 HTTP 采样器,然后选择“添加”>“断言”>“响应断言”。在其设置面板中,您会看到几个部分,包括“要测试的字段”、“模式匹配规则”和“要测试的模式”等。
在“要测试的字段”中,您可以选择要检查的响应部分。最常用的选项包括:文本响应(HTML 正文中的内容)、URL 采样(请求指向的 URL)、响应代码(数字代码,例如 200、404、500、302 等)、响应消息(与代码关联的消息,例如“OK”)、响应标头(响应标头)以及文档(文本),用于分析 Word、PowerPoint 或文本文件等文档中的内容。
在模式匹配规则中,您可以定义如何解释您输入的模式。最常用的选项包括 CONTAINS、MATCHES、EQUALS 和 SUBSTRING。CONTAINS 使用正则表达式 (RegEx) 来验证返回的文本是否包含指定的模式。MATCHES 也使用正则表达式,但要求整个文本都与表达式匹配。EQUALS 适用于纯文本,并且要求完全匹配,而 SUBSTRING 则使用纯文本检查响应是否包含预期的子字符串。
在“待测试模式”部分,您可以添加要验证的文本或模式。例如,您可以指定单词“Welcome”,以确保首页的 HTML 中包含该消息。如果响应不符合断言定义的条件,JMeter 会将样本标记为失败,您可以在监听器中看到此标记。
这种验证至关重要,它能确保性能测试不仅测量时间和负载,还能保证用户看到的内容正确无误。换句话说,服务器响应速度快是不够的,响应必须正确。
使用 Listeners 收集和可视化结果
监听器是 JMeter 中负责收集、存储和显示执行结果的元素。监听器有很多类型(图表、表格、树状图、摘要等等),但对于初学者来说,最有用的类型之一是“查看结果树”。
要添加“查看结果树”,请右键单击线程组或测试计划,然后选择“添加”>“监听器”>“查看结果树”。此监听器会显示测试期间发送的每个样本,以及其请求、响应、计时和任何关联的断言。当您编写第一个脚本并需要调试每个步骤中发生的情况时,它非常理想。
在监听器顶部,您可以指定 JMeter 将以 JTL 或 XML 格式保存结果的文件。您还可以加载先前运行的结果进行重新分析。单击“配置”按钮将打开一个窗口,您可以在其中选择要包含在结果文件中的字段:开始时间、响应时间、发送的字节数、接收的字节数、状态等。
点击工具栏中的“开始”按钮运行测试计划后,您会看到“查看结果树”中显示每个请求的条目。例如,如果您运行两次测试,将会得到两组不同的结果。在第一次运行时,通常会故意导致断言失败(例如,搜索 WelcomeAAA 而不是 Welcome),以便清楚地看到错误请求是如何以红色突出显示的。
如果您展开其中一个失败的请求并选择“响应断言”选项卡,您将看到解释验证失败原因的内部消息。此信息对于调整断言模式和快速检测被测页面上的内容错误非常有用。
在 JMeter 中使用插件管理器和 PerfMon
JMeter 可以通过插件进行扩展,添加新功能、监听器、采样器和监控工具。手动管理这些插件可能很繁琐,因此有一个名为“插件管理器”的实用程序可以大大简化这项任务。
要安装插件管理器,您必须从 JMeter 插件网站下载相应的 JAR 文件,并将其复制到 JMeter 安装目录下的 lib/ext 文件夹中。完成此操作后,如果您之前打开了 JMeter,则需要将其关闭并重新打开。重启后,“选项”菜单中应该会出现一个新选项,确认插件管理器已被识别并集成。
有了插件管理器,您可以从菜单打开它,查看已安装和可用插件的有序列表。标准插件包是最受欢迎的插件包之一。只需在列表中找到它,选中它,然后单击“应用更改并重启 JMeter”按钮。工具重启后,您就可以在性能测试中使用新的元素了。
在该套件的众多组件中,PerfMon 指标收集器监听器尤为突出。该监听器旨在接收来自名为 PerfMon 服务器代理的外部代理的数据,该代理安装在您要监控的机器上(例如应用服务器、数据库等)。它们协同工作,使您能够在负载测试运行时收集系统指标,例如 CPU、内存、磁盘和网络使用情况。
将 JMeter 与 PerfMon 结合使用的最大优势在于,您可以将服务器的内部行为(资源使用情况)与测试结果(响应时间、错误率、吞吐量)直接关联起来。此外,您还可以使用 eBPF 和 PerfMon 来补充分析并监控性能,从而获得更详细的系统指标。因此,如果您观察到在一定用户数量后 CPU 使用率飙升且响应时间显著增加,则说明瓶颈在于处理能力,您可以进一步调查。
将 JMeter 与 PerfMon 结合使用的最大优势在于,您可以将服务器的内部行为(资源使用情况)与测试结果(响应时间、错误率、吞吐量)直接关联起来。因此,如果您观察到在一定用户数量之后 CPU 使用率飙升且响应时间显著增加,则说明瓶颈在于处理能力,您可以进一步调查。
简而言之,插件生态系统为定制 JMeter 以适应各种场景打开了大门,从基本的 Web 测试到涉及多种协议和高级基础设施监控的复杂情况。
精通 Apache JMeter 需要理解性能测试的基础知识,掌握如何正确安装和配置该工具,理解测试计划、线程组、采样器、计时器、断言和监听器等概念,并利用 PerfMon 等插件来全面了解系统行为。如果能够很好地控制这些要素,就能更轻松地构建真实的测试场景,检测容量和稳定性问题,识别负载峰值,并就应用程序是否能够应对实际流量做出明智的决策。
对字节世界和一般技术充满热情的作家。我喜欢通过写作分享我的知识,这就是我在这个博客中要做的,向您展示有关小工具、软件、硬件、技术趋势等的所有最有趣的事情。我的目标是帮助您以简单而有趣的方式畅游数字世界。
