Apache JMeter on GCE 環境構築手順

## 参考情報

### 参考文献

- [Apache JMeter - User's Manual: Remote (Distributed) Testing](https://jmeter.apache.org/usermanual/remote-test.html)
- [VNC 利用手順まとめ - Qiita](https://qiita.com/ryo-sato/items/7cf2da401dd13dd4f36d)
- [SSH 鍵作成手順 - Qiita](https://qiita.com/ryo-sato/items/89c7878885775ac5fe1e)


### 要求スペック

- [jmeter system requirements - Google Search](https://www.google.com/search?hl=en&q=jmeter+system+requirements)
   - 公式サイトに明確なスペックは記載されていないが, 2 コアの CPU に 4 GB のメモリーが基準になりそう。
   - Vagrant + VirtualBox 標準の 1 コア + 512 MB メモリーでは, JMeter 起動時に CPU コア数の警告が表示される上に, 80 MB 程度の SWAP が発生した。

        ```
        OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
        ```

   - 実験した結果, 2 コア, 7.5 GB メモリー (n1-standard-2) でも 100 スレッドは厳しい。
      - 1 スレッドなど, 疎通確認程度なら問題なし。
      - 思い切って n1-standard-8 (8 コア, 30 GB メモリー) にして, ヒープを最小 8 GB, 最大 24 GB に設定した方が確実に負荷を掛けられる。
         - 利用後はきちんとインスタンスを停止, もしくは, 削除すること。


## 準備

1. [SSH 鍵作成手順 - Qiita](https://qiita.com/ryo-sato/items/89c7878885775ac5fe1e) を参考に, SSH 鍵を作成する。
1. [VNC 利用手順まとめ - Qiita](https://qiita.com/ryo-sato/items/7cf2da401dd13dd4f36d) を参考に, VNC Viewer をダウンロードする。


## 構築

大まかな流れは以下の通り。

1. クライアント用インスタンスを作成する。
1. クライアントに SSH 接続し, 以下の通り設定する。(設定はスクリプトで自動インストールする。)
   1. SSH 鍵生成
   1. JMeter インストール
   1. 簡易デスクトップインストール
1. 生成した SSH 鍵を基に, サーバー用インスタンスを作成する。
1. クライアントより, サーバーに JMeter をインストールする。
1. クライアントで rmi_keystore.jks を生成する。
1. 生成した rmi_keystore.jks をサーバーに転送する。
1. JMeter サーバーを起動する。
1. JMeter クライアントを起動する。


### インスタンス作成

1. GCP にログインする。
1. 適切なプロジェクトに変更する。
1. 左ペインより, **Compute Engine** をクリックする。
   - *VM インスタンス* 画面に遷移する。
1. **作成** ボタンを押下する。
1. 以下の通り入力し, **作成** ボタンを押下する。なお, 記載の無い設定は初期値のままとすること。
   - 名前: (今回は以下の通りとする。)
      - クライアント: **jmeter01** (1 台)
      - サーバー: **jmeter11, jmeter12, jmeter13** (3 台)
   - リージョン: **asia-northeast1 (東京)**
   - ゾーン: (今回は以下の通りとする。)
      - jmeter01: **asia-northeast1-b**
      - jmeter11: **asia-northeast1-c**
      - jmeter12: **asia-northeast1-a**
      - jmeter13: **asia-northeast1-b**
   - マシンタイプ:
      - クライアント: **n1-standard-2: vCPU x 2, メモリ 7.5 GB**
      - サーバー: **n1-standard-8: vCPU x 8, メモリ 30 GB**
   - ブートディスク: **CentOS 7**
   - *管理* タブ
      - 起動スクリプト: (後述の起動スクリプトを入力する。)
   - *セキュリティ* タブ
      - SSH 認証鍵:
         - クライアント側は, 事前に生成した公開鍵を指定すること。
         - サーバー側は, クライアント設定時に生成した公開鍵を指定すること。
1. インスタンス作成後, **外部 IP** 宛てに SSH 接続できることを確認する。
1. 起動スクリプトの動作が完了するまで待機する。(一度, OS が再起動すれば完了扱いで OK.)
   - `$ sudo tailf /var/log/messages | grep startup` コマンド, もしくは,
   - GCE: *VM インスタンスの詳細* ページの **シリアルポート 1 (コンソール)** より進捗を確認できる。


#### クライアント起動スクリプト

```bash
#!/bin/bash
## System update
yum -y epel-release
rm -frv /var/cache/yum
yum -y upgrade

if [ ! -f ${HOME}/initialized.log ]; then

    ## Install packages
    yum -y install ansible git tigervnc-server

    ## Make a script for making desktop
    cd /usr/local/etc; pwd
    mkdir -v roles
    cd roles; pwd
    git clone https://github.com/sb3f-ryo-sato/ansible-role-apache-jmeter.git
    git clone https://github.com/sb3f-ryo-sato/ansible-role-legacy-desktop.git

    cd /usr/local/bin; pwd
    echo '#!/bin/bash' | tee setup-desktop.sh
    echo 'ssh-keygen -q -t ed25519 -N "" -f ~/.ssh/id_ed25519' | tee -a setup-desktop.sh
    echo 'cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys' | tee -a setup-desktop.sh
    echo 'echo "StrictHostKeyChecking no" | tee ~/.ssh/config' | tee -a setup-desktop.sh
    echo 'chmod -v 0600 ~/.ssh/authorized_keys ~/.ssh/config' | tee -a setup-desktop.sh

    echo 'cd /usr/local/etc/roles/ansible-role-apache-jmeter/installer; pwd' | tee -a setup-desktop.sh
    echo 'ansible-playbook setup-apache-jmeter-client.yml -i hosts.yml' | tee -a setup-desktop.sh

    echo 'cd /usr/local/etc/roles/ansible-role-legacy-desktop/installer; pwd' | tee -a setup-desktop.sh
    echo 'ansible-playbook setup-legacy-desktop.yml -i hosts.yml' | tee -a setup-desktop.sh

    echo 'cd; pwd' | tee -a setup-desktop.sh
    echo 'cp -afv /etc/skel/.bashrc .' | tee -a setup-desktop.sh
    echo 'cp -afv /etc/skel/.Xresources .' | tee -a setup-desktop.sh
    chmod -v 0755 setup-desktop.sh

    ## Set locale
    localectl set-locale LANG=ja_JP.UTF-8
    localectl status

    ## Set timezone
    timedatectl set-timezone Asia/Tokyo
    timedatectl status
    chronyc -n sources

    ## Make initialized log
    date | tee ${HOME}/initialized.log

    ## Reboot
    systemctl reboot
fi
```


#### サーバー起動スクリプト

```bash
#!/bin/bash
## System update
rm -frv /var/cache/yum
yum -y upgrade

if [ ! -f ${HOME}/initialized.log ]; then

    ## Set locale
    localectl set-locale LANG=ja_JP.UTF-8
    localectl status

    ## Set timezone
    timedatectl set-timezone Asia/Tokyo
    timedatectl status
    chronyc -n sources

    ## Make initialized log
    date | tee ${HOME}/initialized.log

    ## Reboot
    systemctl reboot
fi
```


### クライアント設定, SSH 公開鍵確認

1. クライアントに SSH 接続する。
1. 必要に応じて, クライアント, サーバー両方のヒープサイズを変更する。
   - `$ cd /usr/local/etc/roles/ansible-role-apache-jmeter/installer; pwd`
   - `$ sudo vi hosts.yml`
1. クライアント向けの自動設定を実行する。
   - `$ setup-desktop.sh`
1. 設定有効化のため, 再ログインする。
   - ~/.bashrc と ~/.Xresources が自動的に読み込まれる。
1. SSH 公開鍵の内容を出力する。
   - `$ cat ~/.ssh/id_ed25519.pub`


### サーバー向けインスタンス作成, JMeter インストール

1. 先ほど出力した SSH 公開鍵を基に, サーバー向けのインスタンスを作成する。
   - 起動スクリプトにより, 再起動が完了するまで待機する。
1. サーバー向けインスタンスに JMeter をインストールする。
   - `$ cd /usr/local/etc/roles/ansible-role-apache-jmeter/installer; pwd`
   - `$ ansible-playbook setup-apache-jmeter-server.yml -i hosts.yml`


### rmi_keystore.jks 生成, サーバーに転送, JMeter サーバー起動

1. rmi_keystore.jks を生成する。質問はローマ字で入力すること。
   なお, パスワードは [13.1 Setting up SSL](https://jmeter.apache.org/usermanual/remote-test.html#setup_ssl) に記載されている *default passphrase* とする。
   また, `keytool` コマンドで PKCS12 形式に移行するよう警告が表示されるが, JMeter 起動時にエラーとなる可能性があるため, スキップする。
   - `$ cd /usr/local/apache-jmeter/bin; pwd`
   - `$ LANG=C ./create-rmi-keystore.sh`
      - What is your first and last name?: **(名前)**
      - What is the name of your organizational unit?: **(部署名)**
      - What is the name of your organization?: **(組織名)**
      - What is the name of your City or Locality?: **(区市町村名)**
      - What is the name of your State or Province?: **(都道府県名)**
      - What is the two-letter country code for this unit?: **JP**
      - Is ... correct?: **yes**
1. 生成した rmi_keystore.jks をサーバーに転送する。
   なお, seq の引数はサーバーの台数で決定すること。
   - `$ seq 11 13 | while read LINE; do scp rmi_keystore.jks jmeter${LINE}:/usr/local/apache-jmeter/bin; done`
1. JMeter サーバーを起動する。
   - `$ seq 11 13 | while read LINE; do ssh -n jmeter${LINE} "nohup jmeter-server > /var/tmp/jmeter-server.log 2>&1 &"; done`
   - `$ seq 11 13 | while read LINE; do ssh -n jmeter${LINE} "ps -flyH"; done`
1. クライアントの remote_hosts 行を有効化する。
   - `$ sed -i -e 's/^#remote/remote/g' /usr/local/apache-jmeter/bin/user.properties`


### VNC Server 起動

1. [VNC 利用手順まとめ - Qiita](https://qiita.com/ryo-sato/items/7cf2da401dd13dd4f36d) を参考に, VNC Server を起動する。


### JMeter 起動

- Tera Term の場合
   - `$ DISPLAY=':1' jmeter &`
- X Window System の xterm の場合
   - `$ jmeter &`
- サンプル
   - ![WS000000.PNG](https://qiita-image-store.s3.amazonaws.com/0/124605/42de784d-795a-fdba-28fa-9796841dc72d.png)


### グローバル IP アドレス確認

1. グローバル IP アドレスを確認し, 被テスト対象のファイヤーウォールに設定する。
   - `$ curl ipinfo.io | python -m json.tool`

        ```json
        {
            "city": "",
            "country": "US",
            "hostname": "148.31.200.35.bc.googleusercontent.com",
            "ip": "35.200.31.148",
            "loc": "35.0000,105.0000",
            "org": "AS15169 Google LLC",
            "region": ""
        }
        ```


## 後片付け

### JMeter, VNC Server 終了, VM インスタンスシャットダウン

1. **ファイル - 終了** をクリックする。
   - 必要に応じ, XML ファイルは保存後, SFTP で自端末にダウンロードすること。
1. VNC Server をシャットダウンする。
   - `$ vncserver -kill :1`
1. インスタンスをシャットダウンする。
   - `$ seq 11 13 | while read LINE; do ssh -n jmeter${LINE} "sudo systemctl poweroff"; done`
   - `$ sudo systemctl poweroff`


### インスタンス削除

1. GCP にログインする。
1. 適切なプロジェクトに変更する。
1. 左ペインより, **Compute Engine** をクリックする。
   - *VM インスタンス* 画面に遷移する。
1. 削除するインスタンスにチェックを入れ, **削除 (ゴミ箱アイコン)** ボタンを押下する。
1. *インスタンス削除* ポップアップが表示されるので, **削除** をクリックする。


どっとはらい。