ようへいの日々精進XP

よかろうもん

JMeter でシナリオを書く時に HTTP プロキシサーバを使えば少し捗るかもしれないメモ

台風直撃の朝。

tl;dl

  • 先日立ち上げた Redmine 環境に対して JMeter で負荷テストを行う為のシナリオを作ってみようと思った
  • 但し HTTP リクエストをポチポチ作るのは辛いと思ったら HTTP プロキシサーバ(HTTP(S) Test Script Recorder)という機能を利用すると少し捗りそうな気がした

ということで、雑なメモ。


参考

ありがとうございます。


メモ

JMeter における HTTP プロキシサーバとは

JMeter を日本語環境で起動した場合には「HTTP プロキシサーバ」と表示されるが、JMeter 2.10 以降は HTTP(S) Test Script Recorder という名前の機能のようだ。

いつものざっくり意訳で...

  • JMeter 自体が HTTP(S) プロキシとして動作する
  • ブラウザのプロキシ設定を JMeter プロキシに向けて上げることでブラウザでの操作を記録する

という機能。

準備

ブラウザ側の設定

今回は Google Chrome を利用するので Google Chrome にて Proxy サーバーの設定を行う。

f:id:inokara:20150823165203p:plain

尚、利用した Chrome のバージョンは バージョン 44.0.2403.157 m という最新のバージョン。

JMeter 側の設定

JMeter を起動して以下の設定を行う。

f:id:inokara:20150823163951p:plain

  1. スレッドグループを作成
  2. [ワークベンチ]→[追加]→[Non-Testエレメント]→[HTTP プロキシサーバ]を選択
  3. [対象となるコントローラ]にて 2. で作成したスレッドグループを指定
  4. 任意だが [Add suggested Excludes] をクリックして記録を除外するコンテンツの拡張子を指定する(ことも出来る)
  5. [開始] をクリックして記録を開始する

利用した JMeter のバージョンは 2.13 で Java のバージョンは...

Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

C:\Users\kappa>java -version
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)

C:\Users\kappa>

となる。

記録開始

HTTP プロキシサーバの [開始] をクリックしてブラウザアクセスの記録を開始する。

f:id:inokara:20150824194009p:plain

適当にブラウザアクセスを行う。

f:id:inokara:20150824194321p:plain

リクエストの内容を見てみる

ひとしきりブラウザアクセスをしたら [停止] をクリックして「HTTP リクエスト」の内容を見てみる。

f:id:inokara:20150824194620p:plain

ちゃんと HTTPS アクセスで POST メソッドの内容も記録されている。

実際にシナリオを利用して負荷をかけてみる(1)

記録したシナリオを利用して負荷を掛けてみると以下のようにログイン、ログアウトの処理が失敗している。

f:id:inokara:20150825063527p:plain

理由は...

  • Rails アプリケーションは CSRF(クロスサイトリクエストフォージェリ )対策がデフォルトで行われておりリクエストパラメータに authenticity_token というパラメータを付与する
  • 今回 HTTP プロキシサーバで記録された authenticity_token の値が不正な値として検証に失敗しログイン、ログアウトの処理でエラーが発生してしまっている為

Redmine の production.log にも以下のように記録されている。

Started GET "/login" for xxx.xxx.xxx.xxx at 2015-08-24 20:19:32 +0000
Processing by AccountController#login as HTML
  Current user: anonymous
  Rendered account/login.html.erb within layouts/base (2.2ms)
Completed 200 OK in 20ms (Views: 14.3ms | ActiveRecord: 0.9ms)
Started POST "/login" for xxx.xxx.xxx.xxx at 2015-08-24 20:19:32 +0000
Processing by AccountController#login as HTML
  Parameters: {"utf8"=>"?", "authenticity_token"=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==", "back_url"=>"http://xxx.xxx.xxx.xxx/", "username"=>"user", "password"=>"[FILTERED]", "login"=>"ログイン ≫"}
Can't verify CSRF token authenticity

CSRF 対策の処理を HTTP リクエストに加える

ということで...

CSRF 対策の処理は各アプリケーションによって若干は異なるかもしれないが、Redmine の場合には /login の場合には最初に GET /login の際にレスポンスボディの meta-data 含まれる csrf-token から取得する。

f:id:inokara:20150825063608p:plain

  • 参照名には LOGIN_CSRF_TOKEN を定義して後の [HTTP リクエスト] で参照出来るようにする
  • 正規表現には を指定して meta-data から csrf-token を取得する
  • テンプレートには $1$ を指定する

[HTTP リクエスト] に [後処理] → [追加] → [正規表現抽出] で追加して、上記のパラメータを定義しておく。

次に実際のログイン処理を行う POST /login 処理のパラメータとして csrf-token を利用するように設定する。

f:id:inokara:20150825063622p:plain

  • authenticity_token に上記で定義しておいた参照名(LOGIN_CSRF_TOKEN)を変数として定義する
  • その他のパラメータについては記録された状態の値を踏襲する

[HTTP プロキシサーバ]で記録しておいたパラメータに対して上記の通りの修正を加える。尚、ログアウトの処理(/logout)に関しても同様の処理を行う。

尚、以下にサンプルのシナリオをアップしておく。

github.com

実際にシナリオを利用して負荷をかけてみる(2)

最後に cookie も利用しているようなので [oreno-thread] → [追加] → [HTTP クッキーマネージャ] でスレッドグループに追加してから改めて記録したシナリオで負荷を掛けてみる。

f:id:inokara:20150825063640p:plain

とりあえず全てのアクセスが成功していることを確認。

f:id:inokara:20150825063654p:plain

[統計レポート] でもリクエストエラー等は検出されていないことを確認。


まとめ

HTTP プロキシサーバを利用することで

  • [HTTP リクエスト] を書く手間が省ける
  • ログイン、ログアウト処理等がある場合には適宜一手間加える必要がある

Rails アプリケーションでログイン、ログアウトの処理をシナリオにする場合には

  • CSRF 対策が入っている(Rails 4 以上はデフォルトで設定されているとのこと)
  • [正規表現抽出] を利用してログイン処理前等のレスポンスヘッダ、レスポンスボディから CSRF トークンを取得してログイン処理に含めるようにする
  • [HTTP クッキーマネージャ] も追加しておくと良さそう

その他

  • [結果をツリーで表示] を設定しておくと [HTTP リクエスト] のデバッグに役立つ

ということで、やっと負荷試験を出来る準備が整った。

以上。