負荷テスト対象のWebアプリがこういう非機能要件(+α)を備えていたらいいのにという願望

はじめに

 「Software Test & Quality Advent Calendar 2011」のエントリーとして書いております。
 Software Test & Quality Advent Calendar 2011の参加者は結構真面目なエントリを皆様書いてますが、このエントリは、ある意味愚痴です。

 Software Test & Quality Advent Calendar 2011の前日のエントリは以下の2つでした。

 いつかどこかで、「プログラムは、ユニットテストしやすいように作った方が良い」という趣旨の文章をよみました。
 だったら、「Webアプリは、負荷テストをしやすいように作った方が良い。いや、作ってくれると嬉しいなぁ…」ということを言ってみるのもありかもしれない、と思ったのでそういう話を書きます。
 範囲としては、測定、測定結果の分析に関して「こうなってると楽なんだけど」といった辺りです。

 「負荷テストって、どのタイミングで何目的にする奴を想定してるの?」って辺りには触れていませんが、主にプロジェクトが終わりかけた頃に実施される奴を想定して書いています。

 クリスマス企画だし願望を書いても良いよね。
 

主な対象読者

  • 開発者(こう作ってくれると嬉しいな、という話ですので)
  • 負荷テストを行う方(あるあるネタ的な意味で、面白がってもらえれば…)


対象とするアプリ

  • 小規模な業務系Webアプリ。DBはOracle。言語は、Java。あまりそこが大事になる話は出てきませんが。


サーバ編

APサーバとDBサーバのマシンは分かれていると嬉しい

 仮想でも良いから、分かれていると嬉しいです。
 その方が、サーバのリソース使用状況を計るツールを使いやすいからです。

 APサーバとDBサーバが分かれていると、「どのサーバのCPUの負荷が高い」といったレベルで情報を収集すれば多くの場合事足ります。
 しかし、同居していると「どのプロセスがCPUのパワーをどれだけ使っている」といった感じになってしまいます。
 で、これを調べるようにツールを設定したり、あるいは情報収集したりするのは面倒です。
 あるいは、方法がわからないことも。

 余談ですが、仮想の場合、リソースの割り振りルールがどうなっているかを知っておくのは大事です。
 意外なところではまったのは、OSを論理区画に分けるタイプの仮想化。
 負荷に応じてCPUの割り当て量がすごく変わる奴に遭遇しまして、仮想化されたOS上でCPU使用率をはかると、常に100%近くになっているという…。今から思えば、論理区画のCPUの使用率が概ね100%になるように、割り当て量が動的に変化していたのだと思います。

DBサーバの使用容量は、DBサーバ管理担当に余裕を持って申告をしてくれると嬉しい

 小さなシステムだと、複数のアプリで一つのDBサーバを共有していることがあります。
 こういう場合はDBサーバ管理担当がいて、その方に必要な容量を申告するのですが、この際に計算した容量を正直に申告してしまう人が居ます。

 何が困るかといいますと、負荷テストの前にその申告が必要なケースが多いことです。
 その結果、「ここにインデックス追加すると、パフォーマンスが改善される可能性が高いです」という結果が出た際に、「インデックス用表領域のサイズに余裕がないため、張れない。どうしよう」となることがあります。
 この状態になると、結構頭が痛いです。

フレームワーク

ここでいうフレームワークは、いわゆる業務フレームワーク部分を含みます。

Java側が、どのSQLをどこで発行しているか調査しやすい構造になっていると嬉しい

 業務アプリの場合、RDBMS周りのせいで遅いことが多いです。
 そうすると、DBサーバから収集した情報を元に以下の調査をすることが多いです。

  • 遅いSQLについて、アプリのどの処理と対応しているのか
  • 発行回数が多いSQLについて、アプリのどの処理と対応しているのか

 DB側に記録されている、実際発行されたSQLの一部を条件として、ソースか設定ファイルをgrepすることで、SQLを特定できると助かります。
 APサーバのログから、アプリのどの部分を実行したか追いやすくなっているのであれば、アプリのログにSQLが出力される、とかでも良いです。

 あと、大事なのが「適切に仕組みを使って、アプリを実装して頂く」というのもあります。
 たとえば、せっかくSQL定義を外だしするO/Rマッパを使っているのに、発行するSQLの内容について、動的に決定される部分が多すぎると、やっぱり解析時に苦労します。

アプリのログからトランザクションに要した時間が分かると嬉しい

 DBサーバのログから、「このSQLが遅い」とか「このSQLの発行回数が多い」とかは分かっても、「アプリから実行した、このトランザクションが遅い」とかは分からないものです(多分)。  よって、トランザクションの実行時間が読み取れるようになっていると大変助かります。

 「トランザクションの開始、実行のログ」以外に、同時使用ユーザ数が多い場合は、各行に以下の情報が無いと苦労します。

  • スレッド名
  • セッションID
  • (ログイン処理がある場合)ユーザID

 スレッド名のみでもある程度追えそうなものですが、人間が目でログを追うことが多いので、情報量が少ないとミスがね…。

プロファイラ無しでも、ある程度プロファイリングできると嬉しい

 「アプリのログからトランザクションに要した時間が分かると嬉しい」とある程度重なるのですが、処理の実行時間がある程度分かると嬉しいです。
 やはりJavaのロジックが遅いこともありますので。

 どれぐらいの粒度で処理時間が分かると嬉しい、というのは一言では上手く言えないのが、困ったところですが…。

 ボトルネックを解析する際には、教科書どおりの答えとしては「プロファイラを使ってボトルネックを調べましょう」となるのかもしれませんが、以下の理由によってプロファイラはあまり役にたったこと無いです。

  • APサーバの起動がやたら遅くなる。起動終了まで待っていられない。
  • 業務ロジックと関係ないメソッドの処理時間が、「時間の掛かった処理」の上位に上がってきて、どう解析して良いか途方に暮れる

クライアントが叩くURLと投げるデータが分かりやすいと嬉しい

 URLの生成ルールが複雑だと、JMeterでシナリオを作るときに、もうね…。
 Wicketもクライアントが叩くURLがやや複雑ですが、もう正規表現Wicketが生成するURLを抽出するのに慣れましたので、Wicketについては個人的にはどうでも良いです。

 あと投げるデータについても、以下が分からないと苦しむので、ドキュメントが残っていると助かります。

  • セキュリティ対策
  • ASP.NETでいうところのViewState的なものがあるならば、その仕様(一般的になんていうのだろう?)


開発中編

マスタ系データは開発の初期から件数だけでも揃えてあると嬉しい

 開発者は、開発中も動作確認のためにたびたびプログラムを動かすわけです。
 いわば、プチ負荷テストをしているといっても過言では無いでしょう。

 ということは、早い段階からデータの件数だけでも揃えておけば負荷テストの段階になって「え。なんでこんな基本的な操作が遅いの…?」と頭を抱えることが減るはずです。
 0にはならないでしょうけどね。

バグは、誰が発見した場合でも「リリース前に見つかって良かったね」という文化だと嬉しい

 これはプロジェクトがぎすぎすしていると、パフォーマンスに問題があることに気付いた人がいても、それを上に伝えないのですよ。
 バグですら言いにくいのですから、正常に動作するものを誰が申告するでしょうか。

 よって、報告しやすい文化だと、負荷テストの段階になって「え。なんでこんな基本的な操作が遅いの…?」と頭を抱えることが減るはずです。

さいごに

 「え?負荷テストと関係無くない? どちらかというと運用の容易性を上げるという話だよね、これ」と思った方は、ある意味正解です。
 負荷テストは、「動かしてみないと分からない問題を、本番で発生する前に潰そう」という側面があります。運用が始まってからのトラブルシュートが考慮されているシステムならば、負荷テストもまたやりやすいです(運用で発生するトラブルは性能問題以外もあるので、逆は言えないですが)。

 大規模のアプリにとっては普通の考慮かもしれませんが、小さいアプリだとこういった考慮を忘れたりするもの。
 予算と工数の兼ね合いもありますが、小さなアプリでもこういった考慮を入れて頂けると、意外な人が喜んでくれるかもしれません。