foregoで始める検証生活

性能検証を実施する際には、負荷テスト・ツールで負荷をかけるだけではなく、vmstatやiostatなどによるサーバー・リソースのモニタリングが必用です。負荷テスト・ツールとモニタリング・ツールを同時に実行するのにforegoが便利なので、foreogoの使用例をまとめます。

foregoとは？
------------

foregoは複数のプロセスを管理するツールです。同じ作者によるforemanというRubyでかかれたツールのGo実装です。foremanの方が広く使われているのですが、一般的に検証環境はインターネットに接続されておらず、Rubyをインストールするのは手間がかかるのでシングル・バイナリで提供されているforegoを使います。

[forego: Foreman in Go](https://github.com/ddollar/forego)

foregoのインストール
--------------------

foregoのインストールは、[foregoのダウンロードページ](https://dl.equinox.io/ddollar/forego/stable)から圧縮されたファイルをダウンロードし、展開するだけです。debやrpmパッケージもありますが、検証環境を汚さないように、ここでは使用しません。

Procfileの記述
--------------

foregoはProcfileというファイルに記述された複数のプロセスを管理します。Procfileには `プロセス名: コマンド` という書式で起動するプロセスを記述します。

例えば、cpu、io、iostat、vmstatというプロセスを以下のように記述します。

```:Procfile
cpu: ./cpu.sh
io: ./io.sh
iostat: ./iostat.sh
vmstat: ./vmstat.sh
```

実行
----

Procfileに定義した全てのプロセスを一度に起動します。Ctrl + Cでforegoを停止すると、起動した全てのプロセスが停止します。

```console
forego start
```

並列度を変更することもできます。

```console
forego start -c cpu=2,io=0,iostat=0,vmstat=1
```

タスクの定義例
--------------

cpu、ioというタスクは負荷がけのタスクです。
cpu.shはCPU負荷の高い処理です。cpu.shの中身は`yes > /dev/null`なので何も出力せず意味は無いのですが、実行時刻と環境変数TEST_CASEで決まるログ・ファイルを作成します。

```bash:cpu.sh
#!/bin/bash

logfile="log/$(date +%Y_%m_%d_%H_%M_%S)_${TEST_CASE}_cpu_$$.log"
exec &> >(tee "$logfile")

yes > /dev/null
```

io.shはI/O負荷の高い処理です。io.shはどのディレクトリにファイルを作成するかを環境変数TEMPFILEで指定します。

```bash:io.sh
#!/bin/bash

logfile="log/$(date +%Y_%m_%d_%H_%M_%S)_${TEST_CASE}_io_$$.log"
exec &> >(tee "$logfile")

tempfile="${TEMPFILE:-$HOME/tempfile}"
echo "tempfile is $tempfile"

while :
do
  dd if=/dev/zero of="$tempfile" bs=1M count=1024 oflag=direct
done
```

vmstat、iostatというタスクはそれぞれvmstatとiostatを使ってリソース監視をするタスクです。

```bash:iostat.sh
#!/bin/bash

logfile="log/$(date +%Y_%m_%d_%H_%M_%S)_${TEST_CASE}_iostat.log"
exec &> >(tee "$logfile")

iostat -t -x 1
```

```bash:vmstat.sh
#!/bin/bash

logfile="log/$(date +%Y_%m_%d_%H_%M_%S)_${TEST_CASE}_vmstat.log"
exec &> >(tee "$logfile")

vmstat -n -t 1
```

実行例
------

```
$ forego start
forego   | starting cpu.1 on port 5000
forego   | starting io.1 on port 5100
forego   | starting iostat.1 on port 5300
forego   | starting vmstat.1 on port 5600
io.1     | tempfile is /home/vagrant/tempfile
vmstat.1 | procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------ ---timestamp---
vmstat.1 |  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
vmstat.1 |  6  1      0  82924   7612 304772    0    0   175  2376  162   81  4  2 94  0  0     2017-03-08 09:40:16 UTC
iostat.1 | Linux 2.6.32-642.el6.x86_64 (ol68)   03/08/2017      _x86_64_        (1 CPU)
iostat.1 |
iostat.1 | 03/08/2017 09:40:16 AM
iostat.1 | avg-cpu:  %user   %nice %system %iowait  %steal   %idle
iostat.1 |            3.60    0.00    1.97    0.49    0.00   93.93
iostat.1 |
iostat.1 | Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
iostat.1 | sda               0.61   156.37    7.77   38.43   349.25  4754.26   110.46     0.99   21.35    4.01   24.86   0.46   2.11
iostat.1 | dm-0              0.00     0.00    8.08  191.58   347.12  1532.48     9.41    28.50  142.76    4.14  148.61   0.10   1.95
iostat.1 | dm-1              0.00     0.00    0.05    0.00     0.43     0.00     8.00     0.00    0.50    0.50    0.00   0.29   0.00
iostat.1 | dm-2              0.00     0.00    0.06    3.19     0.50  3222.14   991.65     0.00    0.97    1.17    0.96   0.55   0.18
iostat.1 |
vmstat.1 |  3  1      0  82620   7648 304816    0    0     8 950272 3585 2972 76 24  0  0  0    2017-03-08 09:40:17 UTC
iostat.1 | 03/08/2017 09:40:17 AM
iostat.1 | avg-cpu:  %user   %nice %system %iowait  %steal   %idle
iostat.1 |           74.75    0.00   25.25    0.00    0.00    0.00
iostat.1 |
iostat.1 | Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
iostat.1 | sda               0.00     0.00    2.02 1874.75    16.16 1919741.41  1022.91     1.71    0.91    0.50    0.91   0.53  99.80
iostat.1 | dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
iostat.1 | dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
iostat.1 | dm-2              0.00     0.00    2.02 1872.73    16.16 1917672.73  1022.91     1.71    0.92    0.50    0.92   0.53 100.00
iostat.1 |
io.1     | 1024+0 records in
io.1     | 1024+0 records out
io.1     | 1073741824 bytes (1.1 GB) copied, 1.1494 s, 934 MB/s
^C      | ctrl-c detected
forego   | sending SIGTERM to iostat.1
forego   | sending SIGTERM to vmstat.1
forego   | sending SIGTERM to cpu.1
forego   | sending SIGTERM to io.1
$ ls log
2017_03_08_09_40_16__cpu_3412.log  2017_03_08_09_40_16__io_3413.log  2017_03_08_09_40_16__iostat.log  2017_03_08_09_40_16__vmstat.log
```