使用 Apache JMeter 规划负载测试

已完成

在本部分中,你将了解负载测试,并了解如何向管道添加负载测试。 负载测试使用 Apache JMeter 模拟同时访问 Web 应用的多个用户。 测试从运行在 Azure 应用服务中的 暂存环境 的应用程序提取 Web 内容。

Tim 首先在笔记本电脑上打开 Apache JMeter 用户界面。 他运行一个基本的测试计划。 然后 Tim 和 Mara 将测试计划导出到可从命令行运行的文件。 最后,将任务添加到 Azure Pipelines,以便在 过渡期间运行负载测试。

注释

为简洁起见,无需在本地计算机上安装 Apache JMeter。 你可以跟着一起阅读。

从 Apache JMeter 运行负载测试

Apache JMeter 是一种开源负载测试工具,用于分析和度量性能。 它生成的报表是一个 XML 文件。

Azure Pipelines 可以读取 Apache JMeter 报表并生成图形。 无需任何特殊的硬件即可运行这些测试,因此可以使用Microsoft托管的代理来运行这些测试。 在太空游戏场景中,你可能会在预发布环境中运行这些测试。

创建测试计划

下面是运行 Linux 的笔记本电脑上的 Apache JMeter 的外观:

Apache JMeter 用户界面的屏幕截图。

你将创建新的测试计划文件;例如 LoadTest.jmx。 然后将 线程组 添加到该文件。 每个模拟用户在其自己的线程上运行。 线程组控制用户数和每个用户的请求数。

以下示例显示了 10 个模拟用户(线程)。 每个用户发出 10 个请求,因此系统总共收到 100 个请求。

在 Apache JMeter 中指定线程组的屏幕截图。

采样器是由 JMeter 发出的单个请求。 JMeter 可以通过 HTTP、FTP、TCP 和其他几种协议查询服务器。 采样器生成添加到报表的结果。

接下来,将 Http 请求默认值Http 请求 采样器添加到线程组。 你将提供在 Azure 应用服务上的过渡环境中运行的 Space Game 网站的主机名。

显示在 Apache JMeter 中指定 HTTP 请求的屏幕截图。

上述方案创建基本测试计划。

运行测试计划

使用 JMeter 可以运行多种测试。 可以从 JMeter 图形用户界面运行测试计划。 但是,对于负载测试,JMeter 文档建议从命令行运行测试计划。

你将使用以下命令运行测试计划:

apache-jmeter-5.4.1/bin/./jmeter -n -t LoadTest.jmx -o Results.xml

-n 参数指定在非 GUI 模式下运行 JMeter。 该 -t 参数指定测试计划文件 LoadTest.jmx。 该 -o 参数指定报表文件 ,Results.xml

JMeter 运行并生成报表文件, Results.xml。 此文件示例显示了前几个结果:

<?xml version="1.0" encoding="UTF-8"?>
<testResults version="1.2">
<httpSample t="180" it="0" lt="95" ct="35" ts="1569306009772" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40871" sby="144" ng="1" na="1">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>
<httpSample t="174" it="0" lt="96" ct="38" ts="1569306009955" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40869" sby="144" ng="1" na="1">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>
<httpSample t="160" it="0" lt="121" ct="35" ts="1569306010131" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40879" sby="144" ng="2" na="2">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>

每个示例在报表中生成一个节点。 该 t 属性指定响应时间(毫秒)。 在这里,你看到三个请求分别用了 180 毫秒、174 毫秒和 160 毫秒。

理想的请求时间应小于 1 秒。 不超过 10% 的请求应占用 1 秒以上。 可以将 JMeter 配置为报告统计信息,例如最小、最大值和平均响应时间或标准偏差。 可以编写脚本来帮助提供此信息。

若要可视化测试结果,需要以 Azure Pipelines 理解的格式提供它们。 Azure Pipelines 可以分析包含测试结果的 XML 文件,但该文件需要采用受支持的格式。 支持的格式包括 CTest、JUnit(包括 PHPUnit)、NUnit 2、NUnit 3、Visual Studio Test(TRX)和 xUnit 2。 可以编写将 JMeter 结果转换为 JUnit 的 XSLT 文件。

将报表转换为 JUnit

XSLT 代表 XSL 转换eXtensible Stylesheet 语言转换。 XSLT 文件类似于 XML 文件,但它使你可以将 XML 文档转换为另一种 XML 格式。

回顾负载测试的要求:

  • 平均请求时间应小于 1 秒。
  • 不超过 10% 的请求应占用 1 秒以上。

下面是满足这些要求的 XSLT 文件如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
  <xsl:template match="/testResults">
    <xsl:variable name="times" select="./httpSample/@t" />
    <xsl:variable name="failures" select="./httpSample/assertionResult/failureMessage" />
    <xsl:variable name="threshold" select="1000" />
    <testsuite>
      <xsl:attribute name="tests"><xsl:value-of select="count($times)" /></xsl:attribute>
      <xsl:attribute name="failures"><xsl:value-of select="count($failures)" /></xsl:attribute> 
      <testcase>
          <xsl:variable name="avg-time" select="sum($times) div count($times)" />
          <xsl:attribute name="name">Average Response Time</xsl:attribute>
          <xsl:attribute name="time"><xsl:value-of select="format-number($avg-time div 1000,'#.##')"/></xsl:attribute>
          <xsl:if test="$avg-time > $threshold">
            <failure>Average response time of <xsl:value-of select="format-number($avg-time,'#.##')"/> exceeds <xsl:value-of select="$threshold"/> ms threshold.</failure>
          </xsl:if> 
      </testcase>
      <testcase>
          <xsl:variable name="exceeds-threshold" select="count($times[. > $threshold])" />
          <xsl:attribute name="name">Max Response Time</xsl:attribute>
          <xsl:attribute name="time"><xsl:value-of select="math:max($times) div 1000"/></xsl:attribute>
          <xsl:if test="$exceeds-threshold > count($times) * 0.1">
            <failure><xsl:value-of select="format-number($exceeds-threshold div count($times) * 100,'#.##')"/>% of requests exceed <xsl:value-of select="$threshold"/> ms threshold.</failure>
          </xsl:if>
      </testcase>
    </testsuite>
  </xsl:template>
</xsl:stylesheet>

我们不会深入探讨 XSL 在这里的工作原理。 但概括而言,此文件首先从 JMeter 输出中收集以下数据:

  • 每个 HTTP 请求时间。

    它通过从每个t元素中选择httpSample属性来收集此数据。 (./httpSample/@t

  • 每条失败消息。

    它通过从文档中选择所有 failureMessage 节点来收集此数据。 (./httpSample/assertionResult/failureMessage

XSLT 文件还将阈值设置为 1,000 毫秒。 此响应时间是我们之前定义的最大值。

鉴于这些变量,XSLT 文件提供测试总数和失败总数。 然后,它提供以下两个测试用例:

  • 平均响应时间,如果平均值超过阈值 1,000 毫秒,则失败。
  • 最大响应时间,如果超过 10% 的请求超过阈值 1,000 毫秒,则失败。

XSLT 的结果与 Azure Pipelines 理解的 JUnit 格式匹配。 可以命名 XSLT 文件 JMeter2JUnit.xsl

接下来,需要 XSLT 处理器。 在此示例中,我们将使用 xsltproc,它是将 XSLT 样式表应用于 XML 文档的命令行工具。

可以安装 xsltproc ,如下所示:

sudo apt-get install xsltproc

接下来,运行 xsltproc 将 JMeter 报表转换为 JUnit:

xsltproc JMeter2JUnit.xsl Results.xml > JUnit.xml

下面是生成的 JUnit 文件, JUnit.xml

<?xml version="1.0" encoding="UTF-8"?>
<testsuite xmlns:math="http://exslt.org/math" tests="100" failures="0">
  <testcase name="Average Response Time" time="0.17"/>
  <testcase name="Max Response Time" time="0.373"/>
</testsuite>

在此示例中,平均响应时间为 170 毫秒。 最大响应时间为 373 毫秒。 两个测试用例都不会生成失败,因为两次都低于 1,000 毫秒的阈值。

稍后,你将在管道中运行这些测试。 可以将 JMeter 写入的文件Results.xml视为未发布到管道测试结果的中间文件。 JUnit.xml 是最终报告文件。 此文件将发布到管道,以便团队能够直观显示结果。