黄脳エンジニアメモ

仕事や趣味やらで調べたり試したりした情報をただただ書き並べてるだけ

*

[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なのかわからない。もっと均等に負荷を与える必要があると判断。

25秒周期で負荷が変動してしまう

25秒周期で負荷が変動してしまう

周期性といえば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-graph2

コンカレントGCに変更したときのJmeterの負荷

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を少ないスレッド数で不可をかけて使っています。

ページ: 1 2

 - Web, 性能 , , , , ,

  関連記事

no image
[GoogleAnalytics]Google アナリティクスのCookie

はじめに Googleアナリティクスはアクセス解析のために、ブラウザから様々な情 …

no image
[AjaXplorer]レンタルサーバのファイル管理

レンタルサーバのファイル管理するエクスプローラがほしい サーバにはレンタルサーバ …

no image
[AWS]ELBがURLで振り分けできない問題はCloudFrontでなんとかする

一般的なロードバランサではできるのにELBでできないURLでの振り分け AWSで …

no image
[GoogleAnalytics]ページアクセスのトラッキング時に送信している情報を調べた

Googleアナリティクスで送信されている情報はどんなのがあるか調べた Goog …