mstoneでメール関連の負荷テスト

詳しくは

* http://mstone.sourceforge.net//doc/mstone.html

をどうぞ。

## インストール

CentOS 6 の場合 make cmake gcc g++ gnuplot pth-devel あたりをインストールしておきます。

```console
$ wget "https://jaist.dl.sourceforge.net/project/mstone/mstone/4.9.4/mstone%2Bdocs-4.9.4.tar.gz"
$ tar xvf mstone+docs-4.9.4.tar.gz
$ cd mstone-4.9.4/
```

CMakeLists.txt 冒頭に

```cmake
cmake_minimum_required(VERSION 3.5)
```

を追加します。(CentOS6 辺りの cmake なら警告出るだけなので追加不要かな)

$HOME/mstone 以下にインストールします。

```console
$ cd ..
$ mkdir build && cd build
$ cmake -DCMAKE_INSTALL_PREFIX=$HOME -DSVN_MODULE=OFF ../mstone-4.9.4
$ make && make install
```
(ソースを展開した場所と別の場所でビルドするようにしてるだけで、別に展開した場所で実行しても構いません)

svn サポートは無視するので `-DSVN_MODULE=OFF` を指定します。でないと GSS_LIB が NOTFOUND とかなんとかエラーになります。

```
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
GSS_LIB
```

`make install`が成功すると、`$HOME/mstone` 以下にインストールされているはず。

## セットアップ

セットアップでテストに必要なファイルをテンポラリディレクトリにコピーする作業をしていますので、別のホストからmstone一式を持ってきたとか、テンポラリディレクトリを/tmpにしてたりして、掃除されてしまってる場合とかはこの作業が必要です(通常は`/var/tmp`がテンポラリディレクトリになってます)。

```console
$ cd $HOME/mstone
$ ./mstone setup
Netscape Mailstone.
Copyright (c) 1997-2000 Netscape Communications Corp.

  : (略)

Do you agree to the terms of the license? (yes/no) yes

Found these message files:
en-17k.msg en-1k.msg en-20k.msg en-2k.msg en-32k.msg en-3k.msg en-5k.msg en-750.msg en-gif-17k.msg gr-3k.msg nu-5k.msg words-ascii.dat

Copying build/Linux4.9_x86_64/mailclient and message files to /var/tmp/
Linux enterprise 4.9.0-plamo64 #3 SMP PREEMPT Mon Dec 19 17:42:58 JST 2016 x86_64 GNU/Linux

$ 
```

## テスト設定

### ローカルから単独実行

* テストは localhost から単独実行
* メールサーバは mailhost.example.com
* サーバ上のユーザは user0 ~ user10 まで (通し番号)
* 上記ユーザのパスワードは hogehoge


```console
$ ./mstone config
Netscape Mailstone.
Copyright (c) 1997-2000 Netscape Communications Corp.


Configure test clients [n]? y

    You can enter multiple machines like this: host1,host2

What is the name of the client(s) for default OS [localhost]: 

What additional client(s) [none]: 

Configure SMTP/POP/IMAP protocols [n]? y

What is the name of the mail host [mailhost.example.com]: mailhost.example.com

What is the user name pattern [mailtestuser%ld]: user%ld

What is the password pattern [myPassword]: hogehoge        

How many users [100]: 10

What is the first user number [0]: 

Do you want to view the new conf/general.wld [y]? n

Configure SVN support [n]? n

Generate an account LDIF file for Netscape Directory Server [n]? n

Make any additional changes to conf/general.wld and then re-run 'setup'
```

出来上がった conf/general.wld は

```xml
$ cat conf/general.wld
# common setup info for tests
# See sample.wld for detailed usage

# Information on how the test is distributed and reported
# Test independent configuration
<CONFIG>
  # Debug with short runs and a few clients, then increase test time
  # These get overridden in the test specific files (or the command line)
  clientCount	2	# nominal clientCount (usually overriden)
  rampTime 	20s
  time		1m

  # Each test should set a title/comments in their CONFIG section
  # This is a reminder to set something
  title		Need to set test title...
  comments      Some sort of testing...
  #sysConfig 	conf/sample.html	# File for additonal system config

  # Uncomment this to enable core dumps:
  #clientCommand ulimit -Sc 900000; ./mailclient
</CONFIG>

# Each <Monitor> section defines remote monitoring commands 
#   for one or more machines.
# Commands containing '%c' run to completion.  
#  Otherwise the command will be shutdown down
<MONITOR>
  name          vmstat.txt            # outfile will be CLIENT*-NAME
  command       vmstat %f
  process       conf/clean_vmstat.pl  # custom processing script
</MONITOR>

# The PreTest sections will run before the test starts
<PRETEST>
  name    preifconfig.txt  # outfile will be CLIENT*-NAME
  command	ifconfig
</PRETEST>

# The PostTest sections will run after the test ends
<POSTTEST>
  name 		ifconfig.txt  # outfile will be CLIENT*-NAME
  command	ifconfig; uname -a
  # clean_ifconfig expects the input name to be preifconfig.txt or pretest.txt
  process       conf/clean_ifconfig.pl  # custom processing script
</POSTTEST>

# The <DEFAULT> tag sets protocol block defaults
<DEFAULT>
  # defaults for both e-mail and revision control systems
  loginFormat	user%ld
  passwdFormat	hogehoge
  numLogins	10
  firstLogin	0

  # e-mail defaults
  server	mailhost.example.com
  smtpMailFrom	user0@mailhost.example.com
  addressFormat	user%ld@mailhost.example.com
  numAddresses	10
  firstAddress	0

  # revision control system defaults
  repoUrl       http://myLocalSvn
  topDir 	repoTop/mstone

</DEFAULT>


# Specify client machines
# mstone assigns the same process/thread counts to each host in a client block.
# Use one host per client block for maximum allocation flexibility.
<CLIENT HOSTS=localhost>
  maxThreads 100
</CLIENT>
```

このファイルは後ほど使われます。

## SMTP テスト

### テストの定義

`mstone`コマンドの引数でテスト名を指定します。ここでは `smtp` というテストを実行してみましょう。これは SMTP でメール送信をするテストが定義されていまして、`conf/smtp.wld` で定義されています。

標準配布のもの以外にも自分で以下のような定義ファイルを定義できます。

```xml
<includeOnce conf/general.wld>

<CONFIG>        # test specific config
  title         SMTP message deliveries
  clientCount   20
</CONFIG>

# if we include more than one, we get a distribution of all sizes
<include conf/smtp1k.wld>
<include conf/smtp5k.wld>
<include conf/smtp17k.wld>
```

* `conf/general.wld` を include して
* `conf/smtp{1,5,17}k.wld` を include します

ここで include されている smtp1k.wld は、

```xml
<SMTP>
weight 100
file en-1k.msg
numRecips 1     # メール宛先の数
numLoops 1      # number of messages to send per login
</SMTP>
```
(コメントは一部追加・削除してます)

* SMTP で送信するファイルとして `en-1k.msg` を使用する
  * `en-1k.msg` は `data/en-1k.msg` です。
* このテストを実行する比率を `weight` で 100 に設定 (他のテストで設定された `weight` との比率になります)

ちなみに `data` 以下にはテストで送信するテスト用のメールデータが保存されていますが、見るとわかりますが、全部 spam メールっぽいものです。薬の販売とか昔良くあったアドビのソフトを売るよとか。Why?

### テストの実行

* mailhost.example.com 上の user0 〜 user10 ユーザに対して
* 10 同時接続で (-l 10)
* 10 同時接続は 10 秒で起動
* 60 秒間 (-t 60s)

テストを行ってみます。

```console
$ ./mstone smtp -t 60s -l 10 -r 10s
Mstone version 4.9.4
Copyright (c) Netscape Communications Corp. 1997-2000

Starting time: Fri Feb  3 15:14:49 2017
Running pretest on localhost 	(results/20170203.1514/localhost-log-preifconfig.txt)
Running monitor on localhost 	(results/20170203.1514/localhost-log-vmstat.txt)
Starting clients (errors logged to results/20170203.1514/stderr)
Starting 1 x 10 on localhost

Rampup time: 10 seconds.  Test duration: 60 seconds.  Clients: 10
Created results/index.html
Index of runs: 	file:///home/ore/mstone/results/index.html
Results (HTML):	results/20170203.1514/results.html
Updating... Fri Feb  3 15:15:34 2017:  Reported duration 42sec (10 clients)
Process 32270 exited (0).
Shutting down monitors: 32269
Running posttest on localhost 	(results/20170203.1514/localhost-log-ifconfig.txt)

Clients done: Fri Feb  3 15:16:04 2017
Collecting results
Reported duration 58sec (10 clients)
Generating results pages
Processing done: Fri Feb  3 15:16:04 2017

Results (text):	results/20170203.1514/results.txt
Results (HTML):	results/20170203.1514/results.html
Index of runs: 	file:///home/ore/mstone/results/index.html
Error log: 	results/20170203.1514/stderr (lines: 23)
Mailmaster done: Fri Feb  3 15:16:04 2017
```

`Could not find/open font when opening font "arial", using internal non-scalable font` みたいな警告が出るときは

```console
$ export GDFONTPATH=/usr/share/fonts/vlgothic/
$ export GNUPLOT_DEFAULT_GDFONT=VL-Gothic-Regular
```

ってな感じにしておきましょう。出力されるグラフもフォントがキレイに出力されますよ。

結果は results/ 以下に出力されます。

## SMTPとIMAP4の同時テスト

### テストの定義

以下のような定義ファイル `my_imapsmtp.wld` を作成してみました。

```xml
<includeOnce conf/general.wld>

<CONFIG>	# test specific config
  title		IMAP, SMTP combined load
</CONFIG>

<SMTP>
  weight 50
  file en-5k.msg
  numRecips 1
  numLoops 1
</SMTP>

<IMAP4>
  weight        200
  leaveMailOnServer     1

  idleTime      2s
  loopDelay     1m
  numLoops      10
  blockTime     2s
</IMAP4>
```

* SMTP:IMAP4 = 1:4 (50:200)
* SMTP テスト
  * メールとして en-5k.msg を使用
  * 1 セッションでメール 1 通送信
  * 1 通の送信で宛先 (RCPT TO) は 1 度送信
* IMAP4 テスト
  * サーバに接続してから 2 秒待ち
  * メールチェックの間隔は 1 分
  * メール取得のループを 10 回繰り返した後サーバとの接続を切る
  * ログアウトした後、次のログインまでの間隔は 2 秒

IMAP4 の場合は繋ぎっぱなしが普通ですから、メールのチェックやら取得のループを 1000 回分繰り返すことにしています。その後はログアウトして、まだテスト継続時間なら再度ログインするという感じになるんだと思います。

### テストの実行

テスト名として `my_imapsmtp` を与えて mstone を実行するだけです。

```console
$ ./mstone my_imapsmtp -t 60s -l 5 -r 1s
Mstone version 4.9.4
Copyright (c) Netscape Communications Corp. 1997-2000

Starting time: Fri Feb  3 18:43:29 2017
Running pretest on localhost 	(results/20170203.1843/localhost-log-preifconfig.txt)
Running monitor on localhost 	(results/20170203.1843/localhost-log-vmstat.txt)
Starting clients (errors logged to results/20170203.1843/stderr)
Starting 1 x 5 on localhost

Rampup time: 1 seconds.  Test duration: 60 seconds.  Clients: 5
Index of runs: 	file:///home/ore/mstone/results/index.html
Results (HTML):	results/20170203.1843/results.html
Updating... Fri Feb  3 18:44:14 2017:  Reported duration 42sec (5 clients)
Process 1816 exited (0).
Shutting down monitors: 1815
Running posttest on localhost 	(results/20170203.1843/localhost-log-ifconfig.txt)

Clients done: Fri Feb  3 18:45:00 2017
Collecting results
Reported duration 74sec (5 clients)
Generating results pages
Processing done: Fri Feb  3 18:45:00 2017

Results (text):	results/20170203.1843/results.txt
Results (HTML):	results/20170203.1843/results.html
Index of runs: 	file:///home/ore/mstone/results/index.html
Error log: 	results/20170203.1843/stderr (lines: 23)
Mailmaster done: Fri Feb  3 18:45:00 2017
```

## モニタ

テスト実行中に何かモニタリングするためにコマンドを実行したい場合があると思います。デフォルトではテストクライアントで vmstat を実行したりしています。

そのような場合 `<MONITOR>` セクションを定義すれば良いです。

```xml
<MONITOR HOSTS=mailhost.example.com>
  name vmstat
  commmand vmstat %f
  rsh ssh
</MONITOR>

<MONITOR HOSTS=mailhost.example.com>
  name iostat
  commmand iostat -x %f
  rsh ssh
</MONITOR>
```

これで
* HOSTS に指定したホストに対して
* `rsh` で指定したリモート接続コマンドを用いて
* `command` で指定したコマンドを実行
  * `%f` は mstone がモニタを実行する頻度に置き換えられます (2 が使われるようですが変える方法はあるのかな?)
というような風にリモートホストのリソース消費なんかがモニタリングできます。負荷テストでは必要ですよね。

前述の定義だと `vmstat 2` と `iostat -x 2` が `mailhost.example.com` 上で実行されます。

この結果は `results/(日時文字列)/mailhost.example.com-log-vmstat` とか `results/(日時文字列)/mailhost.example.com-log-iostat` というファイルに保存されます。