2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

Gatling 与 JMeter,性能测试工具该选谁

作者:Andrzej Ludwikowski

  • 2022-08-03
  • 本文字数:5165 字

    阅读完需:约 17 分钟

Gatling与JMeter,性能测试工具该选谁

JMeterGatling是性能测试工具中的佼佼者。现在已经有很多关于比较这两个工具的文章,那么为什么我还要再这篇文章呢?我将从一个不一样的角度来比较这两个工具。这两个工具我都用了很长一段时间了,我想是时候总结一下我的经验了。

完美的性能测试应该是怎样的

 

从开发人员的角度来看,测试应用程序的性能是开发人员的职责。因此,让一个从未接触过应用程序源代码的测试团队来测试应用程序的性能,这种方法是行不通的。我并不是说测试人员就无法进行良好的性能测试,我想强调的是,如果我们有专门的性能测试人员,那么从一开始就应该让测试人员和开发人员进行密切的合作。

 

随着时间的推移,越来越多的责任会转移到测试团队,但开发人员仍然需要对结果进行分析。当结果与我们最初的预期不同时,就尤为如此。当然,这对开发人员来说是有好处的,因为它创建了一个与解决方案质量相关的反馈循环,类似于单元测试、集成测试或端到端(E2E)测试。

 

性能测试无疑是软件开发当中成本最高的一种测试。测试人员或开发人员需要花宝贵的时间创建它们,除此之外,它们还需要一个专门的(如果可能的话)测试环境。应用程序的变化非常频繁,性能测试需要跟踪这些变化,并保持最新,这比最初创建测试时的成本更高。

 

基于上述原因,关于性能测试,我的第一个建议是用长期的思维来考虑整个测试过程。理想情况下,性能测试应该是持续部署(CD)的一部分。但这并不一定总能实现,也并不一定是有意义的。然而,根据我的观察,在一开始的性能测试中走捷径可能会让我们在未来付出更大的代价。

如何选择性能测试工具

 

选择性能测试工具是第一个难题,我希望本文能够帮助你做出正确的选择。

 

从开发人员的角度来看,一个好的性能测试工具应该具备以下四个主要属性。

 

  1. 可读性;

  2. 可组合性;

  3. 正确的指标;

  4. 分布式负载生成。

 

你可能会说:“就这样?”是的。这些是在选择工具时最重要的考虑因素。当然,还有很多其他特定的功能,尽管大多数工具在创建测试场景、模拟流量等方面提供了或多或少类似的选项。所以,在选择一个既方便又可维护的工具时,我会把重点放在这些要点上。

 

只有当一个工具满足了这四个基本要求,我们才能继续了解它提供的其他功能。否则,如果只是受到一些有趣功能的诱惑,从长远来看,这些功能可能既不有趣也不是很有用,它将变成一个不那么好的工具。

可读性

 

我们先从第一点开始。比较带有 GUI 的应用程序的可读性是一种非常不寻常的方法,我们来看看它会产生怎样的结果。JMeter 中的一个简单的业务流程可能如下所示。


 

乍一看,相当不错。一切都很清楚,我们很容易就可以理解测试的是什么。问题是,随着我们开始扩展场景,添加新的测试步骤,参数化当前步骤或改变它们的行为,那么很快,我们就会得出这样的结论:这是一项非常乏味的工作。你必须经常使用鼠标,知道什么东西藏在哪里,更糟糕的是,你需要记住各个查询之间的隐式连接(例如,共享变量)。

 

根据我的经验,在 GUI 上编辑测试用例迟早会变得不那么令人感到愉快,我们将切换到编辑 XML 格式的源代码,而 XML 格式的源代码(通常是 XML 格式)可读性很差。在 XML 中,我们能够做的就是使用最基础的基于字符串的编辑技术,例如“替换”等。

 

<?xml version="1.0" encoding="UTF-8"?><jmeterTestPlan version="1.2" properties="5.0" jmeter="5.3"></jmeterTestPlan>  <hashTree></hashTree>    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true"></TestPlan>      <stringProp name="TestPlan.comments"></stringProp>      <boolProp name="TestPlan.functional_mode">false</boolProp>      <boolProp name="TestPlan.tearDown_on_shutdown">True</boolProp>      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>      <elementProp name="TestPlan.user_defined_variables" elementtype="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"></elementProp>        <collectionProp name="Arguments.arguments"></collectionProp>      </elementProp>      <stringProp name="TestPlan.user_define_classpath"></stringProp>      ...	  That's a very, very long XML.      ...
复制代码

 

完整的 XML 代码在这里

 

在 Gatling 中,同样的场景看起来像这样。

  val scn =    scenario("Example scenario")      .exec(http("go to main page").get("/"))      .exec(http("find computer").get("/computers?f=macbook"))      .exec(http("edit computer").get("/computers/6"))      .exec(http("go to main page").get("/"))      .repeat(4, "page") {        exec(http("go to page").get("/computers?p=${page}"))      }      .exec(http("go to create new computer page").get("/computers/new"))      .exec(        http("create new computer")          .post("/computers")          .formParam("name", "Beautiful Computer")          .formParam("introduced", "2012-05-30")          .formParam("discontinued", "")          .formParam("company", "37")      )
复制代码

 

它与 JMeter 非常相似,也就是说,你可以看到正在测试的内容以及整体流程。不过,我们不要忘了,这段源代码的可读性几乎和普通语句一样。我们首先会想到的是,既然是源代码,那么我们就可以使用所有已知的重构方法来扩展场景或提高其可读性。

 

Scala(Gatling 中使用的是 Scala)是一种高度类型化的语言,构造场景的大多数问题将在编译代码时被发现。而在 JMeter 中,只有当场景启动时才会检查错误,这肯定会降低结果反馈循环的速度。

 

源代码的另一个好处是,测试的版本管理将变得非常容易,并且可以让其他程序员(甚至是来自不同的团队)评审它们。如果你不得不面对数千行 XML,那么只能祝你好运。

可组合性

 

如果我们需要创建多个共享某些逻辑的性能测试,例如身份验证、用户创建等,可组合性是至关重要的。在 JMeter 中,我们只能通过非常快速的复制粘贴来编辑这些测试。即使是这个简单的测试也存在重复的片段。



随着时间的推移,需要重复的地方会越来越多。不仅是单个请求,整个业务逻辑片段都需要被复制。你可以使用Module Controller来解决这个问题,或者用 Groovy 或 BeanShell 创建自己的扩展。从我的经验来看,这样做非常不方便而且容易出错。

 

在 Gatling 中,构建可重用的片段基本上只受编程技能的限制。第一步是提取出一些可以被多次使用的方法。

 

  private val goToMainPage = http("go to main page").get("/")

private def findComputer(name: String) = http("find computer").get(s"/computers?f=${name}")

private def editComputer(id: Int) = http("edit computer").get(s"/computers/${id}")

private def goToPage(page: Int) = http("go to page").get(s"/computers?p=${page}")

private val goToCreateNewComputerPage = http("go to create new computer page").get("/computers/new")

private def createNewComputer(name: String) = http("create new computer") .post("/computers") .formParam("name", name) .formParam("introduced", "2012-05-30") .formParam("discontinued", "") .formParam("company", "37")

val scn = scenario("Example scenario") .exec(goToMainPage) .exec(findComputer("macbook")) .exec(editComputer(6)) .exec(goToMainPage) .exec(goToPage(1)) .exec(goToPage(1)) .exec(goToPage(3)) .exec(goToPage(10)) .exec(goToCreateNewComputerPage) .exec(createNewComputer("Awesome computer"))
复制代码

 

接下来,我们可以将场景划分为更小的片段,然后组合它们并创建出更复杂的业务流程。

 

  val search = exec(goToMainPage)    .exec(findComputer("macbook"))    .exec(editComputer(6))

val jumpBetweenPages = exec(goToPage(1)) .exec(goToPage(1)) .exec(goToPage(3)) .exec(goToPage(10))

val addComputer = exec(goToMainPage) .exec(goToCreateNewComputerPage) .exec(createNewComputer("Awesome computer"))

val scn = scenario("Example scenario") .exec(search, jumpBetweenPages, addComputer)
复制代码

 

如果我们需要长期维护性能测试,那么毫无疑问,与其他工具相比,高可组合性将是一个优势。根据我的观察,似乎只有那些支持通过源代码来编写测试用例的工具,例如 Gatling 和 Scala、Locust和 Python、WRK2和 Lua 符合这个标准。如果测试用例是用 XML、JSON 等文本格式保存的,那么可组合性总是会受到这些格式的限制。

正确的指标

 

每一个性能测试人员应该都听到过这个说法:“谎言、该死的谎言和统计数据。”如果他们还没听到过,那么他们肯定会以一种非常痛苦的方式学上一课。我们可以用一整篇文章来讨论为什么这句话会成为性能测试领域的咒语。简而言之:中位数、算术平均值、标准偏差在这个领域是完全无用的指标(你只能把它们当作额外的见解)。你可以在 Gil Tene(Azul 的首席技术官和联合创始人)的精彩演讲中获得更多细节。因此,如果性能测试工具只提供这种静态数据,那么你可以立即把它丢掉。

 

衡量和比较性能的唯一有意义的指标是百分比,但在使用它们时要注意它们是如何实现的。通常,它们是基于算术平均值和标准偏差实现的,这导致它们变得不那么有用。

 

你可以从上面的演讲视频中学习如何验证百分比的正确性。

 

另一种方法是自己检查实现指标的源代码。但遗憾的是,大多数性能测试工具文档并没有涵盖如何计算百分比。即使有这样的文档,也很少有人会去阅读它,因此可能会掉入一些陷阱,例如Dropwizard框架指标的实现

 

如果没有正确的数学/统计数据,我们在性能测试方面所做的工作都是毫无价值的,因为我们将无法理解单个测试的结果或结果之间的比较。

 

我在进行性能测试时通常会使用百分比可随着时间发生变化的图形,Gatling 和 JMeter 都提供了这些功能。我们因此能够判断被测试的系统在整个测试过程中是否存在性能问题。



要比较各个测试的结果,你需要使用全局百分比(在两个工具中都可用)。但 JMeter 全局百分比的准确性可能是个问题。Gatling 使用HdrHistogram库来计算百分比,在准确性和内存需求之间做出了一个非常合理的折衷。

分布式测试

 

有一些文章讨论了测试工具本身的性能。这在一定程度上也很重要,因为我们需要生成巨大的流量给被测试的系统“施压”。问题在于,现在的应用程序很少是运行在单台机器上的单个实例。我们测试的是包含多个实例的分布式系统,这些实例运行在不同的机器上(通常是动态可伸缩的云解决方案)。单台机器的性能测试无法生成足够的负载来测试这样的环境。因此,我们不应该去关注哪个工具可以在一台机器上产生更多的流量,而是看看有没有可以同时从多台机器运行分布式测试的工具。

 

在这方面,这两个工具打成了平手。我们可以在 Gatling 和 JMeter 中进行手动的分布式测试。此外,我们可以使用现有的解决方案,如FloodGatling Enterprise,为我们自动完成分布式测试。我绝对推荐后者,因为它会为我们节省很多宝贵的时间。

总结

 

尽管本文的基调可能会被认为是在嘲讽 JMeter,但这并不是我的本意,因为这两种工具我都用过。我曾经以为 JMeter 是唯一合理的测试性能工具,但当我开始使用 Gatling 时,我看不到再回到 JMeter 的意义。

 

一个带有图形界面的工具在一开始可能会更容易使用,但对于我来说,将性能测试作为代码的想法更有吸引力。Gatling 的 DSL 使用起来非常方便,具有很强的可读性,维护起来也容易得多。

 

很多人对 Gatling 持怀疑态度,因为它要求学习一门新的编程语言——Scala,而 Scala 被认为是一门很难使用的编程语言。然而,事实并非如此。Scala 有其优点和缺点,要在 Gatling 中使用 Scala,只需要掌握基本的语法知识即可。另外,如果你一直希望在工作中使用 Scala,但由于各种原因无法实现,那么性能(和自动化)测试将是一个将这门语言引入你的生态系统的绝佳机会。需要注意的是,从 Gatling 3.7 开始,你可以使用 Java 了!这将是我下一篇文章的主题。请继续关注。

 

作者简介:

Andrzej Ludwikowski 是SoftwareMill的软件架构师,拥有超过 12 年的商业软件开发经验。他是技术会议发言人和博客作者,领域驱动开发、事件溯源和多语言持久化技术爱好者,喜欢研究系统性能瓶颈问题。他有一个不断追求完美软件架构的梦想,尽管这样的架构可能不存在,但追求梦想本身就是目标。他还是 SoftwareMill Academy 的培训师。

 

原文链接

Gatling vs JMeter - What to Use for Performance Testing

 

2022-08-03 08:0016209

评论 1 条评论

发布
用户头像
图形工具的短板就是与其他工具得交互,及自身的自动化。
2022-09-30 10:17 · 北京
回复
没有更多了
发现更多内容

〖产品思维训练白宝书 - 认知篇②〗- 破局高手都具备的一种底层认知就是产品思维

哈哥撩编程

#产品思维

开源轻量级 IM 框架 MobileIMSDK 的微信小程序端已发布!

JackJiang

网络编程 IM 即时通讯IM

聊聊接口文档的事儿

京茶吉鹿

接口文档 Knife4j swagger2

2023企业上云暨算云融合产业大会在京召开

中国IDC圈

算力 可信云

北京国家会计学院副教授王亚星:智能会计和价值财务有力支撑企业高质量发展

用友BIP

看我如何用定值 Cookie 实现反爬

华为云开发者联盟

爬虫 开发 华为云 华为云开发者联盟 企业号 4 月 PK 榜

CANN训练:模型推理时数据预处理方法及归一化参数计算

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 4 月 PK 榜

最强嘴替:新任技术管理者如何快速成长,完成转型逆袭?

LigaAI

技术管理 管理者 逆袭 技术人成长 企业号 4 月 PK 榜

2023 - Dubbo 谷歌编程之夏报名启动了!

阿里巴巴云原生

阿里云 云原生 dubbo

强强携手促发展 中建信息成为麒麟软件全国总经销商

极客天地

华为云GaussDB践行数字化,护航证券保险高质量发展

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 4 月 PK 榜

教你如何通过CodeArts IDE插件调用API,高效合成语音

华为云开发者联盟

云计算 开发 华为云 华为云开发者联盟 企业号 4 月 PK 榜

【送猫超卡、阿里云代金券】动手体验 SAE+云效 10 分钟快速打通 CI/CD 流水线

阿里巴巴云原生

阿里云 Serverless 云原生

ES和MongoDB:一次别开生面的比较

Java你猿哥

数据库 mongodb elasticsearch ES API

KgCaptcha验证的那些事

宙哈哈

php Python html 验证码

硬核!GitHub置顶102W字Redis高手心法笔记

Java 数据库 redis 缓存 面试

2023 年“和鲸杯”辽宁省普通高等学校本科大学生计算机设计竞赛启动会顺利召开

ModelWhale

大数据 人才培养 数据科学 数据思维 数据竞赛

PHP短信验证码防刷方案

宙哈哈

php html 图片验证码

KgCaptcha验证码实现笔记

宙哈哈

Python html 验证码

软件测试/测试开发丨Docker 搭建Web服务器nginx

测试人

nginx Docker 软件测试 自动化测试 测试开发

统一观测丨使用 Prometheus 监控 Nginx Ingress 网关最佳实践

阿里巴巴云原生

阿里云 云原生 Prometheus

数智时代的来临,养老行业接入人工智能技术已是势不可挡

加入高科技仿生人

人工智能 AI 养老服务 养老

架构训练营模块一作业

请叫我馒头哥丶

架构 架构实战营

LeaRun低代码开发平台 赋能企业快速落地BI大屏

力软低代码开发平台

网站上的视频资源被偷偷转载了...

为自己带盐

知识产权 ffmpeg HLS openssl

没有设计师?没问题!Spring+OpenAI让你也能生成漂亮的图片!

Java你猿哥

Java spring maven API

三点几嚟,饮茶先啦!PaddleSpeech发布全流程粤语语音合成

飞桨PaddlePaddle

人工智能 机器学习 深度学习 语音识别

# 架构实战营-模块1-作业

Geek_e948d4

喜讯!华秋电子荣获深圳市半导体行业协会优秀合作奖

华秋电子

Spring MVC 之 HttpMessageConverter

Java spring Spring MVC

Gatling与JMeter,性能测试工具该选谁_软件工程_InfoQ精选文章