如何创建每小时 peaks/spikes 并且 10 分钟后 returns 正常的 Gatling 模拟?
How can I create a Gatling simulation that peaks/spikes every hour and returns to normal after 10 minutes?
我正在尝试创建一个测试 运行s 10 小时,有 100 个用户。
每小时,我想在 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 个用户,直到模拟结束。
请注意,除了模拟名称外,场景 1 和场景 2 是相同的...必须有更好的方法来实现一个场景或至少使其适用于两个场景。
任何 ideas/help 将不胜感激!
更新:
按照 John 的建议,我尝试了以下代码:
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
}
但是,我没有得到预期的行为:
如果我写了完全相同的行为 "manually",我确实得到了预期的结果:
setUp(scenario.inject(
rampUsers(10) during (1 minute),
nothingFor(2 minute),
rampUsers(10) during (1 minute)
).protocols(httpconf)).maxDuration(3 minutes)
我在这里错过了什么?
您实际上可以手动完成,例如如果你想每 8 小时激增一次,你可以这样做,其中 surgeRampTime
、recoveryTime
和 quiescenceTime
的总和为一个小时:
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()
方法采用可变数量的参数。这意味着它也可以接受参数列表。所以,你可以用 returns 编写一个函数,只是这样一个列表,按照你最喜欢的列表构造逻辑构造。然后,您可以将 return 值从该函数传递给 .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 斜坡可能是浪涌斜坡的最佳选择)和持续时间等等等等
但要带走的原则是:您可以为 return 编写一个函数,否则您必须手动编写代码。
我最终用不同的方法解决了它。
我没有注入用户并尝试删除他们并再次增加,而是增加了所有用户并在场景中使用了暂停时间。
以下是我采取的步骤:
创建并行 运行 的注入场景,一个是您的常规负载,另一个是您希望用作峰值的额外用户:
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))
场景本身在开头有一个参数化的暂停时间,所以你可以选择暂停或不暂停拍摄:
scenario(name).feed(feed).forever() {
doIf(isPeakDelay) {
pause(pauseDuration + getRandomPeakDelayInSeconds)
}
.exec(api.call1)
.exec(api.call2)
....}
(注意加了随机的暂停时间,你不希望所有用户同时射击)
总而言之,在此解决方案中,您最终将同时遇到两个场景 运行ning - 一个场景在整个测试期间对用户进行射击,而第二个场景在测试开始时启动所有峰值用户测试但暂停您配置的峰值之间的间隔时间。
我正在尝试创建一个测试 运行s 10 小时,有 100 个用户。 每小时,我想在 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 个用户,直到模拟结束。
请注意,除了模拟名称外,场景 1 和场景 2 是相同的...必须有更好的方法来实现一个场景或至少使其适用于两个场景。 任何 ideas/help 将不胜感激!
更新:
按照 John 的建议,我尝试了以下代码:
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
}
但是,我没有得到预期的行为:
如果我写了完全相同的行为 "manually",我确实得到了预期的结果:
setUp(scenario.inject(
rampUsers(10) during (1 minute),
nothingFor(2 minute),
rampUsers(10) during (1 minute)
).protocols(httpconf)).maxDuration(3 minutes)
我在这里错过了什么?
您实际上可以手动完成,例如如果你想每 8 小时激增一次,你可以这样做,其中 surgeRampTime
、recoveryTime
和 quiescenceTime
的总和为一个小时:
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()
方法采用可变数量的参数。这意味着它也可以接受参数列表。所以,你可以用 returns 编写一个函数,只是这样一个列表,按照你最喜欢的列表构造逻辑构造。然后,您可以将 return 值从该函数传递给 .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 斜坡可能是浪涌斜坡的最佳选择)和持续时间等等等等
但要带走的原则是:您可以为 return 编写一个函数,否则您必须手动编写代码。
我最终用不同的方法解决了它。 我没有注入用户并尝试删除他们并再次增加,而是增加了所有用户并在场景中使用了暂停时间。
以下是我采取的步骤:
创建并行 运行 的注入场景,一个是您的常规负载,另一个是您希望用作峰值的额外用户:
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))
场景本身在开头有一个参数化的暂停时间,所以你可以选择暂停或不暂停拍摄:
scenario(name).feed(feed).forever() { doIf(isPeakDelay) { pause(pauseDuration + getRandomPeakDelayInSeconds) } .exec(api.call1) .exec(api.call2) ....}
(注意加了随机的暂停时间,你不希望所有用户同时射击)
总而言之,在此解决方案中,您最终将同时遇到两个场景 运行ning - 一个场景在整个测试期间对用户进行射击,而第二个场景在测试开始时启动所有峰值用户测试但暂停您配置的峰值之间的间隔时间。