[Jmeter]負荷があまりかからない場合の対策
2015/01/14
Jmeterちゃんとうごういてないんじゃね
ということはJmeterがリクエストしきれてないと考えるのが妥当。JmeterはWindows2008サーバで動作させているが、CPUもまた60%でメモリもまだ1GBほど余裕がある。じゃあネットワークか?ということでネットワークはギガビットイーサネットであり飽和してない。さらに負荷かけた状態でftpしてもまだ余裕がある。
詳細にリクエストの状態を調べると負荷に周期性があった
どの程度のリクエストが到達しているのかを正確にみるために、apacheにmod_statusを組み込んで(下記のようにhttpd.confにExtendedStatus Onを設定)、リクエスト数をわかるようにした。
SetHandler server-status Order deny,allow Deny from all Allow from localhost ExtendedStatus On
WebAPサーバで下記のようにして状態を取得する、これを5秒間隔で実行し、Total Accessesの値を記録した。5秒間隔なのでこの値の増分を5で割れば、1秒間のリクエスト数がカウントできる。
# curl http://localhost/server-status/?auto Total Accesses: 43244 Total kBytes: 2128 Uptime: 1430 Cpuload: .440583 ReqPerSec: 30.2406 BytesPerSec: 1523.83 BytesPerReq: 50.3902 BusyWorkers: 4 IdleWorkers: 28 Scoreboard: R___________W___________W___W___...................................................................................................................
これをグラフにしてみたのが下図、妙に等間隔でリクエストが出たり出なかったりしているのがわかる。1つが5秒間の平均になるので5個間隔約25秒周期になってるのだ。これでは限界が450なのか200なのかわからない。もっと均等に負荷を与える必要があると判断。
周期性といえばJavaのGCじゃないか?WebAPサーバのGCをログ出しして、GC-viewerでみたが、こんな周期でGCはかかってなかった。んそうじゃくてJmeterでGCがかかってないか?調べたらビンゴ!まったく同じ間隔でFullGCが動いてた。
でも1回のFullGCは400msなのでたまに0.4秒とまるだけなんだが、とまった分FullGC後に一気にリクエストを出してしまのだ。
JmeterのJavaのGC設定をいじってなるべくコンスタントにリクエストするようにする
JavaでGC挙動を平準化する方法としては「コンカレントGC」がある。「“Stop the World”を防ぐコンカレントGCとは?」に詳しい説明がある。なるべくAPをとめないように常にGC処理を行って(多少性能が落ちるが)というもの。ブラウザへのWebサービスではなく、制御のようなコンスタントな処理が要求される場面で使うもの。今回はこのときの最新のjava1.7を利用(古いバージョンではこれは利用できないので注意)。
jemterのJavaの設定(jmeter.bat)は下記(Jmeter2.7の場合)
(省略) set HEAP=-Xms512m -Xmx512m set NEW=-XX:NewSize=128m -XX:MaxNewSize=128m set SURVIVOR=-XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=50% set TENURING=-XX:MaxTenuringThreshold=2 set RMIGC=-Dsun.rmi.dgc.client.gcInterval=600000 -Dsun.rmi.dgc.server.gcInterval=600000 set PERM=-XX:PermSize=64m -XX:MaxPermSize=64m rem set DEBUG=-verbose:gc -XX:+PrintTenuringDistribution (省略)
これを下記に書き換え
(省略) set JVM_ARGS=-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseParNewGC set HEAP=-Xms512m -Xmx512m rem set NEW=-XX:NewSize=128m -XX:MaxNewSize=128m rem set SURVIVOR=-XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=50% set SURVIVOR=-XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 rem set TENURING=-XX:MaxTenuringThreshold=2 set TENURING=-XX:MaxTenuringThreshold=32 set RMIGC=-Dsun.rmi.dgc.client.gcInterval=600000 -Dsun.rmi.dgc.server.gcInterval=600000 set PERM=-XX:PermSize=64m -XX:MaxPermSize=64m rem set DEBUG=-verbose:gc -XX:+PrintTenuringDistribution set DEBUG=-verbose:gc -Xloggc:gc.log (省略)
コンカレントGCでのJmeterのリクエストは均一に
前述の設定をして同じようにjmeterを動作させたところ下図のようになりリクエストがほぼ均等になった。このシステムの場合はせいぜい250req/secが上限でこれ以上のリクエストは応答が長くなるということがわかった。なぜこれ以上の負荷に耐えられなかったのかはtomcatのスレッドダンプでボトルネックがなにかわかった(ここはこの資料の本質ではないのでかかない)。おそらくこのAPの処理ボトルネックを解消すれば同じサーバでもっとスループットを出せるはずといいことはわかった。
Jmeter 2.8以降では内部の処理を効率化してGCの挙動も改善された模様です。ちなみにJmeter2.8+Java7でで上記の設定をした場合としない場合を確認しましたが結果的には大きな差がでないという結果になってしまいました。
FullGCを抑制するのにJavaのパーマネント領域を128MBにしたらデフォルトよりは頻度がかなり軽減されました。また -Xms512m -Xmx512m の部分はメモリがあるようなら1024mなどに変えてもいいかもしれませんが。あまり大きくすると結局FullGCの間隔は広がるんですがFullGCの時間が長くなるのでいろいろ試すといいです。
それでもこのときは400req/secのあたりで負荷がJmeterのボトルネックなのかイマイチスループットが出ない現象がおきています。Jmeter(インスタンス)を複数起動して、複数から負荷をかけたら改善はしたのですが700req/secいっても少し経過すると400req/secに落ちたりしています(JmeterはWindows2008R2 64bit で 24GB-mem 12core なのですが)。
そこで最近ではJmeterのサーバプロセスを10個ぐらい立ち上げJmeterクライアントから10個のJmeterを少ないスレッド数で不可をかけて使っています。
関連記事
-
[GoogleAnalytics]Google アナリティクスのCookie
はじめに Googleアナリティクスはアクセス解析のために、ブラウザから様々な情 …
-
[AjaXplorer]レンタルサーバのファイル管理
レンタルサーバのファイル管理するエクスプローラがほしい サーバにはレンタルサーバ …
-
[AWS]ELBがURLで振り分けできない問題はCloudFrontでなんとかする
一般的なロードバランサではできるのにELBでできないURLでの振り分け AWSで …
-
[GoogleAnalytics]ページアクセスのトラッキング時に送信している情報を調べた
Googleアナリティクスで送信されている情報はどんなのがあるか調べた Goog …