【问题标题】:How can I create a Gatling simulation that peaks/spikes every hour and returns to normal after 10 minutes?如何创建一个每小时达到峰值/峰值并在 10 分钟后恢复正常的加特林模拟?
【发布时间】:2019-11-27 15:11:56
【问题描述】:

我正在尝试创建一个针对 100 个用户运行 10 小时的测试。 每小时,我想在 10 分钟内将用户数量增加 50,然后再去 回到 100 个用户。请注意,我说的是用户数量而不是 TPS。

由于在一次场景中找不到任何正常的方法,因此我考虑了以下方法。我创建了两个场景并同时运行它们:

  setUp(scenario1.inject(rampConcurrentUsers(1) to (100) during (10 minutes))
    .protocols(httpconf),
    scenario2.inject(nothingFor(60 minutes), rampUsers(50) during (10 minute)).protocols(httpconf))
    .maxDuration(10 hours))

这个模拟的问题是从场景 2 开始增加的用户永远不会停止,所以一个小时后我最终有 150 个用户,直到模拟结束。

请注意,Scenario1 和scenario2 除了模拟名称之外是相同的......必须有更好的方法来实现这一点,或者至少让它与两个场景一起工作。 任何想法/帮助将不胜感激!

更新:

按照约翰的建议,我尝试了以下代码:

 setUp(fastZappingSpeed.inject(nothingFor(1 second),sInjection(1): _*
  ).protocols(httpconf)).maxDuration(6 minutes)

  def sInjection( hours : Int )  = {
    val seq = Seq(rampUsers(10) during (1 minute))
    var i = hours
    while ( i > 0 ) {
      seq  ++ Seq(nothingFor(2 minute)) ++ Seq(rampUsers(10) during (1 minute))
      i -= 1
    }
    seq
  }

但是,我没有得到预期的行为:

如果我“手动”编写完全相同的行为,我确实得到了预期的结果:

  setUp(scenario.inject(
    rampUsers(10) during (1 minute),
    nothingFor(2 minute),
    rampUsers(10) during (1 minute)
  ).protocols(httpconf)).maxDuration(3 minutes)

我在这里错过了什么?

【问题讨论】:

  • 注意,你正在传递 sInjection(1),这意味着你有一个恰好一个凹凸的序列。如果你想要 2 个凹凸,你需要传入 2 个。
  • 这只是我粘贴的一个示例...查看我添加的帖子,我使用不同的方法解决了这个问题。

标签: gatling


【解决方案1】:

您实际上可以手动完成,例如如果你想每 8 小时激增一次,你可以这样做,surgeRampTimerecoveryTimequiescenceTime 的总和为一个小时:

setUp( behavior.inject(
  rampUsers( 0 ) to ( baseline ) during ( rampUpTime ),

  // first surge
  rampUsers( baseline ) to ( surge    ) during ( surgeRampTime ),
  rampUsers( surge    ) to ( baseline ) during ( recoveryTime ),
  constantConcurrentUsers  ( baseline ) during ( quiescenceTime ),

  // second surge 
  rampUsers( baseline ) to ( surge    ) during ( surgeRampTime ),
  rampUsers( surge    ) to ( baseline ) during ( recoveryTime ),
  constantConcurrentUsers  ( baseline ) during ( quiescenceTime ),

  ...

  // final surge 
  rampUsers( baseline ) to ( surge    ) during ( surgeRampTime ),
  rampUsers( surge    ) to ( baseline ) during ( recoveryTime ),
  constantConcurrentUsers  ( baseline ) during ( quiescenceTime ),

  // end of test ramp down
  rampUsers( baseline ) to ( 0 ) during ( rampDownTime )

当然,您可能已经想到了这一点,并且不喜欢它,因为它是一种令人讨厌的编程方式。你想要一种更优雅的方式来完成同样的事情。

秘密在于,.inject() 方法采用可变数量的参数。这意味着它也可以接受参数列表。因此,您可以编写一个仅返回这样一个列表的函数,该列表以您最喜欢的列表构造逻辑构造。然后,您可以将该函数的返回值传递给.inject() 方法,并获得相同的结果。例如:

setUp( behavior.inject( surgeInjection( 8 ) ) )

现在您需要做的就是构建surgeInjection 函数,它可能看起来像这样。

def surgeInjection( cycles : Int ) : List[InjectionProfileFactory] = {
  var list = new List[InjectionProfileFactory]()
  list += ( rampUsers( 0 ) to ( baseline ) over ( rampUpTime ) )
  var i = cycles // or use your favorite looping construct here
  while ( i > 0 ) {
    // adjust the functions to match your injection type (open or closed model)
    list += rampUsers( baseline ) to ( surge )    during ( surgeRampTime )
    list += rampUsers( surge    ) to ( baseline ) during ( recoverTime )
    list += constantConcurrentUsers  ( baseline ) during ( quiescenceTime )
    i -= 1
  }
  list += rampUsers( baseline ) to ( 0 ) during ( rampDownTime )
  return list
}

现在,显然,这更像是伪代码而不是真实代码。你会想要使用正确的注入函数,参数化东西以使其可重用,定义基线注入水平,浪涌水平,使用哪种斜坡来提升用户(我建议 Heaviside 斜坡可能是浪涌斜坡的最佳选择)和持续时间等,等等,等等。

但要带走的原则是:您可以编写一个函数来返回您必须手动编码的内容。

【讨论】:

  • 非常感谢!我没有意识到可以注入一系列“行为”并且您的功能解决方案非常出色。
  • 我尝试了您的建议,但仍然失败,您可以查看更新后的帖子以获取更多信息。
【解决方案2】:

我最终用不同的方法解决了这个问题。 我没有注入用户并尝试删除它们,然后它们再次增加,而是增加了所有用户并在场景中使用了暂停时间。

这是我采取的步骤:

  1. 为并行运行的注入场景创建,一个是您的常用负载,另一个是您希望用作峰值的其他用户:

    setUp(scenario.inject(rampConcurrentUsers(1) to (numberOfTestUsers) during (Config.rampUpDuration minutes))
      .protocols(httpconf),
      peakScenario.inject(rampConcurrentUsers(1) to (numberOfPeakTestUsers) during (Config.rampUpDuration minutes))
        .protocols(httpconf))
    
  2. 场景本身在开始时有一个参数化的暂停时间,因此您可以选择暂停或不暂停:

    scenario(name).feed(feed).forever() {
    
          doIf(isPeakDelay) {
            pause(pauseDuration + getRandomPeakDelayInSeconds)
          }
            .exec(api.call1)
            .exec(api.call2)
           ....}
    

    (注意添加了随机的暂停时间,你不希望所有用户同时拍摄)

回顾一下,在此解决方案中,您最终将有两个并行运行的场景 - 一个场景在整个测试期间拍摄用户,而第二个场景在测试开始时启动所有峰值用户,但暂停为您配置峰之间的间隙时间。

【讨论】:

  • 如果有效,请使用它。但我要提醒的是,加特林的图表并不能清楚地表明正在发生的事情。当你试图描述你对管理层所做的事情时,他们可能不明白。
  • 我还会连续 24 小时运行它,并确保流量不会随着时间的推移而变得顺畅。如果您使用随机暂停,它可能会这样做。慢慢地,也许,但重要的是要确保它足够慢,让您完成预期的跑步持续时间。
  • 谷歌点!我会验证的。非常感谢你的助手!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-06
  • 2019-02-14
  • 2019-11-28
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多