share facebook facebook2 twitter menu hatena pocket slack

2014.06.10 TUE

OS X 10.9 Marvericks に JMeter をインストールして RabbitMQ の負荷テストをした

川原 洋平

WRITTEN BY川原 洋平

cloudpack の 自称 Sensu芸人 の かっぱこと 川原 洋平@inokara)です。

目標

  • jmeter を使って RabbitMQ に負荷を掛ける
  • 負荷をかけてみて sensu で利用する RabbitMQ 用のインスタンスのスペックをざっくり見積もる
  • HA ProxyRoute 53 でのフラッピングを実行して挙動を確認する

task

  • JDK のインストール
  • jmeter のインストール
  • JDK の RabbitMQ プラグインをインストールする
  • シナリオに従い RabbitMQ クラスタに負荷をかける
  • 負荷をかけた状態でクラスタ内のフェールオーバーを試す

設定のStep

JDK のインストール

  1. こちらからダウンロード
  2. 展開
  3. インストーラーをダブルクリックするだけ(簡単)
    20140610_001_install_jdk

jmeter のインストール

  1. バイナリのダウンロードから始める
  2. こちらも展開して適当なディレクトリに移動
  3. バイナリを起動する
    cd $PATH/to/apache-jmeter-2.11/bin/
    java -jar ApacheJMeter.jar
    

    起動すると以下のような画面が表示される。
    20140610_002_install_jmeter
    やったー!

jmeter の RabbitMQ プラグインをインストールする

インストールするプラグイン
jlavallee/JMeter-Rabbit-AMQP

事前準備

  • ant のインストール

プラグインは ant でビルドする必要があるので ant をインストールする。

brew install ant
  • RabbitMQ のクライアントライブラリをダウンロードしてコピーしておく
    wget http://www.rabbitmq.com/releases/rabbitmq-java-client/v3.3.1/rabbitmq-java-client-bin-3.3.1.zip
    unzip rabbitmq-java-client-bin-3.3.1.zip
    cd rabbitmq-java-client-bin-3.3.1
    cp rabbitmq-client.jar ~/bin/$PATH/to/apache-jmeter-2.11/lib/
    
  • プラグインのソースコードを clone する
    git clone https://github.com/jlavallee/JMeter-Rabbit-AMQP.git
    

プラグインのビルドとインストール

  • ant を使ってビルドする
    cd JMeter-Rabbit-AMQP
    ant
    

    しばらくすると…
    20140610_003_build_plugin
    とりあえずビルドは完了!!

  • インストールという名のコピー
    cp /$PATH/to/JMeter-Rabbit-AMQP/target/dist/JMeterAMQP.jar ~/bin/$PATH/to/apache-jmeter-2.11/lib/ext/
    

早速実行や!

簡単なシナリオの作成

シナリオというほどでもないが以下のような条件で ConsumerPublisher のサンプラーを設定してみる。

  • スレッド数 : 50
  • Ramp-Up 期間 : 0
  • ループ回数 : 無限ループ

以下、サンプラーの設定。

20140610_004_make_sceanario

実行!と思った矢先…

JMeter で以下のようなエラーを吐いてしまいテストが実行出来ない…

ERROR - jmeter.threads.JMeterThread: Test failed! java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils
    at com.zeroclue.jmeter.protocol.amqp.AMQPSampler.initChannel(AMQPSampler.java:92)
    at com.zeroclue.jmeter.protocol.amqp.AMQPConsumer.initChannel(AMQPConsumer.java:304)
    at com.zeroclue.jmeter.protocol.amqp.AMQPConsumer.sample(AMQPConsumer.java:56)
    at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:429)
    at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:257)
    at java.lang.Thread.run(Thread.java:744)

以下の Pull Request に基づいて対応。

diff --git a/ivy.xml b/ivy.xml
index dc225ab..3d5e242 100644
--- a/ivy.xml
+++ b/ivy.xml
@@ -5,7 +5,7 @@
     <conf name="runtime" extends="build" description="Libraries that need to be included with project jar" />
     </configurations>
     <dependencies>
-        <dependency org="commons-lang" name="commons-lang" rev="2.4" conf="build->default"/>
+        <dependency org="org.apache.commons" name="commons-lang3" rev="3.0" conf="build->default"/>
         <dependency org="commons-io" name="commons-io" rev="1.4" conf="build->default"/>
         <dependency org="commons-jexl" name="commons-jexl" rev="1.1" conf="build->default"/>
         <dependency org="commons-codec" name="commons-codec" rev="1.4" conf="build->default"/>

及び…

diff --git a/src/main/com/zeroclue/jmeter/protocol/amqp/AMQPSampler.java b/src/main/com/zeroclue/jmeter/protocol/amqp/AMQPSampler.java
index 88df892..0d091e0 100644
--- a/src/main/com/zeroclue/jmeter/protocol/amqp/AMQPSampler.java
+++ b/src/main/com/zeroclue/jmeter/protocol/amqp/AMQPSampler.java
@@ -14,7 +14,7 @@ import com.rabbitmq.client.Channel;
 import com.rabbitmq.client.Connection;
 import com.rabbitmq.client.ConnectionFactory;
 import com.rabbitmq.client.MessageProperties;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;</p>

<p>public abstract class AMQPSampler extends AbstractSampler implements ThreadListener {

各ファイル( ivy.yml/src/main/com/zeroclue/jmeter/protocol/amqp/AMQPSampler.java )を上記のように修正して再度の ant を実行。実行後にあらためて JMeterlib/ext/ 以下にコピーして JMeter を再起動する。

気を取り直して負荷をかけてみる

以下のように緑色の矢印アイコンをクリックして実行する。

20140610_005_excute

並行してマシンのリソースも監視したいので RabbitMQHTTP API でメトリクスを取得して Graphite に突っ込んでモニタリングしてみる。

20140610_006_monitoring

t1.micro インスタンスにて RabbitMQ が使用出来るメモリは 240MB 程度と自動計算されており、実際の使用量は 50MB 程度を推移した。

負荷をかけた状態でのクラスタ内のフェールオーバーについて

注意点

  • JMeterDNS キャッシュの影響を受けて JMeter のログには大量の接続エラーが発生してしまった

Route 53 にて

  • 高負荷をかけた状態においても RabbitMQ にアクセスするクライアントはフェールオーバーを検知して接続先の RabbitMQ は正常に切り替わった
  • フェールオーバーに関しては TTLHealt Check の設定により一定の時間を要してしまう(今回の検証では約 30 秒程度でフェールオーバーした)

HA Proxy にて

  • 高負荷をかけた状態においても RabbitMQ にアクセスするクライアントはフェールオーバーを検知して接続先の RabbitMQ は正常に切り替わった
  • フェールオーバーに関して HA Proxy の設定により一定の時間を要してしまう(今回の検証では約 5 秒程度でフェールオーバーした)

まとめ

負荷に対して

  • 基本的には小さいと思われる
  • 但し、t1.micro は辛いかも
  • 但し OS レベルのチューニングは必要になる可能性はある
    • File descriptors
    • Socket descriptors
  • メモリ使用量に関してはノードの物理メモリから RabbitMQ で自動計算され、その値が上限値として設定される
  • また、行儀の悪いアプリケーションの場合にコネクションが滞留してしまい、結果としてキューの滞留等が発生してしまう可能性はある
  • 今のところ Sensu に関しては行儀は良いと思われる

負荷を与えた状態の RabbitMQ のフェールオーバーについて

  • JMeter の場合には DNS キャッシュが効いてしまい正常な計測は出来なかった

気をつけるポイント

  • また、 JMeter が一度起動してしまうと DNS キャッシュが開放されずダウンさせた RabbitMQ ノードにアクセスしてしまった( JMeter を起動する際に -Dsun.net.inetaddr.ttl=0 オプションを指定して起動することでこの問題は回避出来るかもしれない)
  • 完全な RabbitMQ クライアント( Sensu サーバーやクライアント、API)の挙動をエミュレートすることは出来なかった
    • 尚、Sensu サーバーやクライアントについては DNS の変更や HA Proxy のフェールオーバーに追随する

元記事はこちら