如何解读 LocustIO 的输出/模拟短时间用户访问

How to interpret LocustIO's output / simulate short user visits

我喜欢 Locust,但我在解释结果时遇到了问题。

例如我的用例是我有一个请愿网站。我预计 10,000 人会在 12 小时内签署请愿书。

我写了一个模拟用户行为的 locust 文件:

  1. 一些用户加载但不签署请愿书
  2. 一些用户加载并提交无效数据
  3. 一些用户(希望)成功提交。

在现实生活中,用户现在离开了(因为请愿书是 API 而不是主要网站)。

Locust 向我展示了以下内容:

但作为一个 "Locust" 只是一遍又一遍地重复任务,它并不像一个用户。如果我用一群 1 个用户来设置它,那么在一段时间内,这仍然代表许多真实世界的用户;例如在 1 分钟内它可能会执行 5 次任务:那将是 5 个用户。

有什么方法可以解释数据 ("this means we can handle N people/hour"),或者我可以通过某种方式查看每秒或每分钟有多少 "tasks" 得到 运行 等(即蝗虫给我 requests 每秒但不是 tasks)

这是我在某个地方找到的 hacky 方法。我对此不满意,很想听听其他答案。

在我的 HttpLocust (WebsiteUser) 上创建 class 个变量 class:

WebsiteUser.successfulTasks = 0

然后在 UserBehaviour 任务集上:


      @task(1)
      def theTaskThatIsConsideredSuccessful(self):
          WebsiteUser.successfulTasks += 1
          # ...do the work...

      # This runs once regardless how many 'locusts'/users hatch
      def setup(self):
          WebsiteUser.start_time = time.time();
          WebsiteUser.successfulTasks = 0

     # This runs for every user when test is stopped.
     # I could not find another method that did this (tried various combos)
     # It doesn't matter much, you just get N copies of the result!
     def on_stop(self):
          took = time.time() - WebsiteUser.start_time
          total = WebsiteUser.successfulTasks
          avg = took/total
          hr = 60*60/avg
          print("{} successful\nAverage: {}s/success\n{} successful signatures per hour".format(total, avg, hr)

然后设置零 wait_time 和 运行 直到稳定(或出现故障),然后使用网络中的停止按钮停止测试 UI.

输出就像

188 successful
0.2738157498075607s/success
13147.527132862522 successful signatures per hour

我认为这因此给了我服务器可以处理的最大可想象吞吐量(通过更改孵化的用户数来确定,直到出现故障,或者直到平均响应时间变得无法忍受)。

显然真实用户会有停顿,但这使得测试最大值变得更加困难。

缺点

  • 不能使用分布式 Locust 实例
  • 凌乱;也不能 'reset' - 必须退出进程并重新启动以进行另一次测试。

在 Locust 的日志记录级别上实际上并不存在任务。

如果需要,您可以记录自己的假样本,并将其用作您的任务计数器。不幸的是,这会增加您的请求率,但它不会影响平均响应时间等事情。

像这样:

from locust.events import request_success 

...

      @task(1)
      def mytask(self):
          # do your normal requests
          request_success.fire(request_type="task", name="completed", response_time=None, response_length=0)