JMeterをNAT環境で使う機会があったので設定方法まとめた。というかほぼ以下のサイトに書いてあった通りにした。*1
今回は接続周りの設定の話しかしないので、インストール方法、テスト計画の設定方法、サーバ上でのCUIによるテスト実行などについては解説ありません。
JMeterのサーバクライアント間の通信
Apache JMeterは、クライアントアプリケーション(GUI)上で入力したテスト計画を実行するだけではなく、出力したテスト計画をコマンドラインから実行することもできる。さらに、クライアントアプリケーションからサーバにリモート接続し、テスト計画を実行し、その実行結果を表示することもできる。
テスト計画のリモート実行は、テスト実行用のサーバ上でjmeter-serverを起動し、そのサーバのポートにクライアントアプリケーションからソケット接続することでおこなう。さらにjmeter-server上で実行されたテスト計画の実行結果をクライアントアプリケーション上で表示するためには、jmeter-serverからクライアントアプリケーションのポートへの接続が必要になる。
上の図は、それぞれポート一つずつだが、実際にはrmiregistry用のポートも使用する。
SSHによるポート転送
さて、上記の図での「クライアントPC」がNAT環境にあるなどの理由で、サーバから直接接続できない場合について考える。今回は、SSHによるポート転送を使用する。
まず、サーバ・クライアントのどちらからも接続可能な中継サーバを用意する。サーバが中継サーバを兼ねても構わないが、ここでは一応別サーバということにする。
クライアントPCから中継サーバに、以下のようなssh接続をおこなうことでトンネリングをおこなう。(ここでは、クライアントアプリケーションが使用するポート番号を30000、サーバのアドレスを192.0.2.1としている。JMeterにおける設定方法などについては後述)
ssh -R 30000:localhost:30000 192.0.2.1
JMeter(GUI)を実行しているPCから中継サーバに接続をおこない、中継サーバ上でソケットにポート30000番を割り付けて接続を受け付けるようになる。
JMeter Serverでテストが開始されると、結果を送信する為にクライアントへの接続をおこなおうとする。設定(後述)を工夫することで、クライアントPCへ接続する代わりに、中継サーバに接続をおこなうように仕向けることができ、中継サーバ上で先ほどSSHが用意したポートに接続がおこなわれる。中継サーバ上の30000番ポートへの接続は、SSHのポート転送機能によって接続元であるクライアントPCの30000番ポートに転送され、クライアントPC上のJMeterに接続がおこなわれるようにできる。
中継サーバでポート転送をおこなうには、中継サーバのsshdの設定が必要な場合がある。OpenSSHでは、sshd_configで「GatewayPorts yes」を指定する必要があった。
上の例では、テスト実行サーバからクライアントPCへの接続ができない場合の説明であったが、クライアントからサーバへの接続ができない場合も同じようにポート転送で接続を確保できる。
JMeterの設定内容
クライアント、サーバのどちらも相互に接続できないような場合を考える。どちらからも、中継サーバには接続できるとする。中継サーバは下の図のようにインターネット上にあるかもしれないし、サーバ側のDMZ上などにあるかもしれない。
それぞれのIPアドレスを以下のようにする。
中継サーバ | 192.0.2.1(グローバル) |
クライアントPC | 192.168.0.3(プライベート) |
JMeter実行サーバ | 192.168.1.5(プライベート) |
今回使用するポートを以下のように決める。ポート番号は何でも良いが転送できるように固定は必要。
rmiregistryポート | 31099 | デフォルトは1099 |
JMeter サーバが使用するポート | 40000 | デフォルトは不定 |
JMeter クライアントが使用するポート | 30000 | デフォルトは不定 |
クライアントの設定
サーバへの接続を中継サーバに振り替えるために、/etc/hostsに以下の記述をおこなう。
127.0.0.1 localhost jmeter-client 192.0.2.1 jmeter-server
bin/jmeter.properiesの以下の項目を設定する。
remote_hosts=jmeter-server:31099 client.rmi.localport=30000
remote_hostsにはサーバ名とrmiregistryポートを指定する。指定したホスト名がメニューから選択できるようになる。
bin/jmeter.shでJVM_ARGSに以下の引数を追加し、システムプロパティにjava.rmi.server.hostnameを設定する。
JVM_ARGS="-Djava.rmi.server.hostname=jmeter-client"
サーバの設定
クライアントへの接続を中継サーバに振り替えるために、/etc/hostsに以下の記述をおこなう。
192.168.1.5 jmeter-server 192.0.2.1 jmeter-client
bin/jmeter.properiesの以下の項目を設定する。
client.rmi.localport=30000 server.rmi.port=31099 server.rmi.localport=40000
bin/jmeter-serverでRMI_HOST_DEFに以下の引数を追加し、システムプロパティにjava.rmi.server.hostnameを設定する。
RMI_HOST_DEF=-Djava.rmi.server.hostname=jmeter-server
トンネリング設定
サーバから中継サーバに対して、以下のようにSSH接続をおこなう
ssh -ladmin -R 31099:localhost:31099 jmeter-client ssh -ladmin -R 40000:localhost:40000 jmeter-client
クライアントPCから中継サーバに対して、以下のようにSSH接続をおこなう
ssh -ladmin -R 30000:localhost:30000 jmeter-server
必要であれば、サーバ、クライアントPCから上記のポートへの接続をそれぞれFWで許可する。
プログラムの起動
サーバ側でjmeter-serverを起動する
[apache-jmeter-2.9]$ bin/jmeter-server Using local port: 40000 Created remote object: UnicastServerRef [liveRef: [endpoint:[jmeter-server:40000](local),objID:...
クライアント側で、jmeter.shを起動する
[apache-jmeter-2.9]$ bin/jmeter.sh
その他補足
元々クライアント→サーバ間の回線が細かったのでサーバ側で実行しようとして始めたんだけど、リスナー「結果をツリーで表示」などを使用している場合、レスポンスの内容が転送されるので転送量は減らない。「ログエラーのみ」にチェックするか、ネタ元サイト様のようにmode=Asynch設定した方がいいかも。
*1:サーバ側もNATというのは今回追加した条件だけど。