python FunkLoad で WEBの負荷テスト

python FunkLoad で WEBの負荷テストする備忘録メモ

負荷テストといえばJMeterやApache Benchあたりが有名。
ただしJMeterはちょっとリッチで面倒くさそう。
Apache Benchはシンプルだがシナリオがつくれない。
そこでPythonベースでシンプルでシナリオありの負荷試験を簡易的に行えるFunkLoadに出会う。
コンフィグファイルと、数行のpythonテストプログラムを２つ用意するだけでOK。
インストールもpipで一発。



##参考

https://github.com/nuxeo/FunkLoad

https://github.com/nuxeo/FunkLoad/blob/master/src/funkload/demo/simple/Simple.conf

https://qiita.com/terapyon/items/40c226567755f85984a3

http://blog.redturtle.it/2009/11/13/how-to-write-funkload-test-in-few-minutes

# [1] Funk Loadインストール

Amazon-Linuxはpipで入れる

```bash
pip install funkload
```

# [2] テスト用ファイルの準備

準備するのは、負荷試験設定のconfigファイルと、処理内容のpythonのみ

Simple.conf

```bash
[main]
title=Simple FunkLoad tests
description = Simple demo
# 宛先
url = http://localhost:80


[test_simple]
description = Access our Demo app

[ftest]
log_to = console file
log_path = ./output/Simple-test.log
result_path = ./output/simple-test.xml
sleep_time_min = 0
sleep_time_max = 0

[bench]
# 各テストケース(=サイクル)のユーザ数。下記はケース1：1人、ケース２：５人、・・・
cycles = 1:5:10
# 各サイクルの期間（秒）。
duration = 10
# スレッド開始までのwait（秒）
startup_delay = 0
# テスト実行間のwait（テストリクエスト発行間隔）（秒）
sleep_time = 1
# 各サイクル間のwait
cycle_time = 5

# ログ設定
log_to =
log_path = ./output/simple-bench.log
result_path = ./output/simple-bench.xml
# テスト実行間のMAX/MIN wait（テストリクエスト発行間隔）（秒）
sleep_time_min = 0
sleep_time_max = 0
```


test_Simple.py
※単純に「トップ画面で200 OKならよい」というテストシナリオ

```py
import unittest
from random import random
from funkload.FunkLoadTestCase import FunkLoadTestCase

class Simple(FunkLoadTestCase):

    def setUp(self):
        self.server_url = self.conf_get('main', 'url')


    def test_simple(self):
        #ここがテストシナリオ。例では1リクエストのみだが、複数処理書いてもよい。
        server_url = self.server_url
        res = self.get(server_url, description='Get url')
        self.assertEqual(res.code, 200)

if __name__ in ('main', '__main__'):
    unittest.main()
```

# [3] サンプルWEBサイト準備

今回は簡単にdockerでnginxのサイトを立てる

```
docker run -p 80:80 nginx:latest
```

※docker installなどは省略

# [4] テスト実行

コマンド

```bash
fl-run-bench test_Simple.py Simple.test_simple
```

こんな感じで結果が標準出力

```bash
========================================================================
Benching Simple.test_simple
========================================================================
Access our Demo app
------------------------------------------------------------------------

Configuration
=============

* Current time: 2018-09-16T06:23:52.054577
* Configuration file: ~/Simple.conf
* Log xml: ~/output/simple-bench.xml
* Server: http://localhost:80
* Cycles: [1, 5, 10]
* Cycle duration: 10s
* Sleeptime between request: from 0.0s to 0.0s
* Sleeptime between test case: 1.0s
* Startup delay between thread: 0.0s

Benching
========

* setUpBench hook: ... done.

Cycle #0 with 1 virtual users
-----------------------------

* setUpCycle hook: ... done.
* Current time: 2018-09-16T06:23:52.055426
* Starting threads: . done.
* Logging for 10s (until 2018-09-16T06:24:02.056792): .......... done.
* Waiting end of threads: . done.
* Waiting cycle sleeptime 5s: ... done.
* tearDownCycle hook: ... done.
* End of cycle, 15.04s elapsed.
* Cycle result: **SUCCESSFUL**, 10 success, 0 failure, 0 errors.

Cycle #1 with 5 virtual users
-----------------------------

* setUpCycle hook: ... done.
* Current time: 2018-09-16T06:24:07.093412
* Starting threads: ..... done.
* Logging for 10s (until 2018-09-16T06:24:17.103725): .................................................. done.
* Waiting end of threads: ..... done.
* Waiting cycle sleeptime 5s: ... done.
* tearDownCycle hook: ... done.
* End of cycle, 15.06s elapsed.
* Cycle result: **SUCCESSFUL**, 50 success, 0 failure, 0 errors.

Cycle #2 with 10 virtual users
------------------------------

* setUpCycle hook: ... done.
* Current time: 2018-09-16T06:24:22.156211
* Starting threads: ................. done.
* Logging for 10s (until 2018-09-16T06:24:32.190575): ............................................................................................. done.
* Waiting end of threads: ........... done.
* Waiting cycle sleeptime 5s: ... done.
* tearDownCycle hook: ... done.
* End of cycle, 16.05s elapsed.
* Cycle result: **SUCCESSFUL**, 93 success, 0 failure, 0 errors.

* tearDownBench hook: ... done.

Result
======

* Success: 153
* Failures: 0
* Errors: 0

Bench status: **SUCCESSFUL**
```

# [5] 実行結果確認

さっき立てたnginxのaccess.logを確認してみる
access.logは、/etc/nginx/nginx.confでチェック

1st cycleで1sおきに10回、その後5sあけて2nd cycleが5 userから・・・と実際にリクエストを受けていることがわかる。

```bash
172.17.0.1 - - [16/Sep/2018:06:23:52 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:23:53 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:23:54 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:23:55 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:23:56 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:23:57 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:23:58 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:23:59 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:00 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:01 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:07 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:07 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:07 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:07 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:07 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:08 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:08 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:08 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:08 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
172.17.0.1 - - [16/Sep/2018:06:24:08 +0000] "GET / HTTP/1.0" 200 612 "-" "FunkLoad/1.17.1" "-"
：
（以下省略）
```

[6] 実行結果をもっと詳しくチェック

実行結果で出力されるxmlを引数に以下を実行すると、htmlレポートを生成できる

```bash
fl-build-report --html simple-bench.xml
```

![report.png](https://qiita-image-store.s3.amazonaws.com/0/112537/3ad52032-634f-a1d6-6712-d12592d460ce.png)