1.そこが一番知りたいんだよ!具体的な進め方とは?
前回で下記のようなシステム開発のよくある流れについて確認した。
<遅い!→調べた!→とりあえずサーバは強化しておこう→クソコード××!>
少し整理すると、性能改善のためにやるべき事は概ね以下の事になる。
1.現在の状況を監視・計測して事実を認識する
→New Relicを仕込んだり、JMeterで負荷をシミュレートしたりして問題箇所を探る。
2.即効性のある対策で時間稼ぎをしつつ、根本解決に向けた改善活動を進める
→スケールアップやインスタンスタイプの変更、スケールアウトできるならサーバ台数の調整等を行う。
3.性能目標値を決める
→ユーザ数、データ量の増加傾向について試算し、機能毎に重要度・緊急度から優先順位を付けて改善活動のガイドとなる考え方をまとめておく。
4.分析してボトルネックを探す
→プログラムに問題がある場合、New RelicやBlackfireといったプロファイリングツールを駆使してボトルネックを分析する。
5.あらゆる手段で性能改善を行う
→ロジックに改善の余地が無くても、要件を阻害しない範囲で仕様の見直しを含めた対策をひねり出す。
「以上です!」。
これでは表面的な説明だけで「あるある!」と多少の共感を得るだけで終わってしまう。
そこはもう一歩踏み込んでおこう。
<計測して、改善する事を繰り返すのが基本である。>
開発チームが計測と改善も両方やるのであれば、ボトルネックに対する心当たりがあるのは自然なことである。その時も計測する前に直して感覚的に早くなった、というのはあまりオススメできない。慌てずエビデンスを残しながら進めて行く事が重要であると考えて欲しい。
余談だが、一般的に開発に費やす時間よりも、システムが稼働し続けそれを保守し続けることの方がはるかに長い。
その過程では、開発した人と保守する人が違うという状況は当然のようにある。
問題となっている部分の原因を調査するとき、何故そうしたのかという理由や経緯が追跡できることはチームのモチベーションにも影響するし、ひいてはサービスの信頼性を維持向上するために重要なポイントだというのが私の考えである。
2. “超真面目な”現状の監視と計測について
遅いと指摘を受けてしまった場合は、まずその指摘箇所から調査を進めることになるだろう。弊社ではオープンソースのプロダクトを利用することが多く、負荷テストにはApache JMeterを使うことが多い。
Apache JMeter
これは無料なのに十分な機能性があり、基本的な負荷テストはこれだけで用が足りることも多い。
しかし、JMeterは負荷をかけることと、そのサーバからのレスポンスがどうかを計測するのが主な機能である。これだけでは、そのシステムのどのモジュールが遅いのかまでは分からない。DB、IO、ネットワーク、アプリのどれが重いのかはまでは分からないのだ。
そこで、前回も軽く触れたNew RelicやBlackfireを利用することで、どの部分が遅いのかを一目瞭然で調べることが出来る。
一昔前のWebアプリケーションやWeb APIだけで見ればサーバサイドのレスポンスタイムを計測するだけで足りる場合もあるが、昨今のWebアプリケーションについてはReal User Monitoring(RUM)と呼ばれるように実際のユーザが体感している速度を計測して、ユーザ満足度を指標化していこうとする動きがある。
New Relicは、その点を強めに押し出しているように見えるが、実際問題、現代のWebアプリケーションではサーバ側だけが高速であっても、ブラウザ側の処理が遅くモッサリしているというのもしばしば耳にする。
エンドユーザが遅いと感じる原因を考えると、影響のある要素としては以下のものがある。
・クライアントPCの性能
・JavaScriptの処理性能
・サービスとユーザ間のネットワーク
・サーバのロジック性能
・クエリの性能
・DBの性能
・各サーバのIO
これらの全てを計測し判断材料となる情報を提供してくれるAPMツールを選定することは非常に重要なポイントである。
3.スパッと効く即効性のある対策
例えば、JMeterで負荷をかけてみたところ、スレッド数(同時接続ユーザ数)が50を超えた辺りで著しくレスポンスタイムが遅くなることが発覚したとする。
ここで、サービスのオーナー(お客様)と決めなければならないのは以下の2点だ。
▼想定すべき同時接続数
▼レスポンスタイムの許容時間
例えば50名が同時アクセスで5秒以内に応答が無ければならない、という目標値となる。
こうしたとき、改善手段としては
① サーバをスケールアップする
② スケールアウトできるようにアプリケーションを改修する
③ ロジックの性能を改善する
クラウド環境であれば、スケールアップするのが最もコストのかからない対策となる事が多い。
ただ、例えば以下の様な条件があるかも知れない。
▶️同時接続数が50近くなるような時間帯は1日の中でも夜8時〜9時の間
この場合、スケールアップして凌ぐことが出来たとしても、コスト的には最適では無い。同時利用者数が少ない時間帯はオーバースペックとなってしまうためだ。
ピーク時間帯が予想できるのであれば、該当時間帯にスケールアウトするようにオートスケールを構成すれば中長期的にはコストメリットが出てくるだろう。
オートスケールにした場合、アプリケーションのセッション管理をファイルで行っているならば、セッション情報をフロント側で共有する必要があるため、MemcacheやRedisといったキャッシュサーバを使うように構成変更しなければならないだろう。そして、その場合はアプリケーション側でも少なくとも設定変更とテストが必要になる。
まとめ>>
比較的少ない改修で対応可能なインフラ側の手立てとして、以下の流れで対策を打てることが多い。
1.スケールアップしてサービスが止まらないようにする
2.スケールアウトできる構造にアプリケーションを改修する
3.オートスケールにする
しかしながら、本質的にはアプリケーション自体をスリムにしていかなければならない事は忘れないで欲しい。
インフラ側で手を打つというのは、「太ったから着る服のサイズをワンサイズ上げた」と言う意味に近い。
根本的には体を絞って健康にならなければならない、ということなのだ。
さて、次回は・・・「具体的にはどうやって進めるの?」