サービスが使えない状況があってはいけない
近年,私たちは有料無料を問わず,さまざまなサービスを利用できます。外出するときには地図で目的地を確認し,公共交通機関の経路を検索するか,車で通る経路を検索するのではないでしょうか。公共交通機関での移動中には,SNSやゲームをして友人達と交流を深めていることでしょう。仕事でも,会社内で承認を得るための申請サービスなどを使用しているのではないでしょうか。
これらのサービスは,たくさんのユーザーからのリクエストを,短時間で返さないといけません。もし,サービスが満足に使えなくなると,一部のユーザーがSNSで拡散し,その結果ニュースに掲載されてサービスのイメージが低下することもあります。サービスのイメージ低下はサービス提供者のビジネスに影響を及ぼすため,あってはなりません。そのため,サービス提供者は問題の発生をできる限り予防し,問題が発生した場合には即時に対応することが必要となります。
システムの構成要素がどのように連携しているのかを把握する
サービスの多くは,アプリケーション,複数のサーバやネットワーク機器,ハードウェアなどが連携したシステムによって構築されます。問題の発生箇所はこれらの数だけあり,問題の数はこれらの組み合わせの数だけあります。さまざまな問題に対応するためには,システム全体の構成を把握する必要があります。
しかしながら,問題に対応するためにすべての組み合わせを確認するのは,作業が膨大になってしまいます。そのため,それぞれの要素がどのように連携しているのかを把握して,対応範囲を絞ります。以降,Webシステムの例で,システムの構成例を紹介します。
図1 Webシステムの構成例

サーバはハードウェアやOSで構成され,その上で各サーバアプリケーションが実行されます。サーバアプリケーションにはWebサーバ,Javaのアプリケーション,データベースサーバなどがあります。システムは,スイッチやロードバランサーなどのネットワーク機器を使用して,サーバ同士を連携します。ユーザーがサービスを使用してシステムへアクセスすると,各サーバは下記のように連携します。
図2 リクエストからレスポンスへの流れ

それぞれの処理を1つずつ見ていきましょう。
① Webサーバは,ユーザーからのHTTPリクエストを受け取り,必要に応じてHTTPリクエストをJavaアプリケーションへ転送します
② Javaアプリケーションは,受け取ったHTTPリクエストに含まれているURLから実行する処理を決定し,処理を実行します。処理の一部では,データベースサーバへSQLをリクエストします
③ データベースサーバは,SQLを解析/実行して,データをメモリやストレージから取り出し,結果セットとしてJavaアプリケーションへ返信します
④ Javaアプリケーションは,データベースサーバから受け取った結果セットを使用して処理を継続し,処理が完了するとWebサーバへHTTPレスポンスを返信します
⑤ Webサーバは,JavaアプリケーションからのHTTPレスポンスを受け取り,ユーザーへHTTPレスポンスを返信します
情報が不足して,整理できない場合には,誤った結論を導きやすくなる
システム担当者は,システムで問題の発生に備えて,事前にどのような対応をしておくべきなのでしょうか。また,問題発生時に何をしなければならないのでしょうか。例として,サービスの反応がなくなったケースで見てみましょう。
システム担当者はまず,原因を解明するために,発生した事象と現状を把握しなければなりません。事象は「サービスの反応がなくなった」ということなので,Webサーバがリクエストを受け付けてないのか,レスポンスを返していないのかを確認します。現在の状況を確認するため,システム管理者はそれぞれのサーバで取得しているログや,サーバの状況を確認します。
図3 得られた情報

情報を確認したところ,以下のことがわかったとします。
- WebサーバはHTTPリクエストを受け付けていたが,ユーザーへHTTPレスポンスを返してなかった
- Webサーバのアクセス数はわずかに上昇したものの,アクセスの傾向は普段と比べて違いがない
- JavaアプリケーションのCPU使用率は非常に高いが,普段のCPU使用率を取得していないため,普段との差は判断できない
- データベースサーバへクエリを投げてみても,実行時間は感覚的に問題がなさそう
- ネットワークでは,Webサーバ~Javaアプリケーション間の通信量が普段よりも多くなっていた
これらの情報から原因となりそうな箇所を分析すると,以下の可能性が考えられます。
- JavaアプリケーションのCPUリソースが不足しているため,リクエストを処理できていない
- ネットワークの帯域が不足しているために,Webサーバへレスポンスが返っていない
しかし,情報が不足して,情報が整理できない場合には,誤った結論を導きやすくなります。
図4 得られた情報と本当の原因

じつは,本事象は,Javaアプリケーションの処理時間よりWebサーバのタイムアウト時間がわずかに短かいことで起こります。WebサーバがJavaアプリケーションからのレスポンスをタイムアウトして,リクエストをリトライすると,Javaアプリケーションは何度も同じ処理を実行するため,CPU使用率が上がります。何度も結果を返したために,ネットワークの負荷も高まります。Webサーバは,Javaアプリケーションからのレスポンスが返ってこないと,ユーザーへレスポンスを返せません。そのため,ユーザーは「サービスが反応しなくなった」と判断してしまうのです。この問題は,Javaアプリケーションの処理を高速化するか,Webサーバのタイムアウトを伸ばすことで解決できます。
問題の原因を特定するための3つの条件
問題の原因を特定するには,次の3つの条件を守らなくてはいけません。
- 得られた情報が定量的であること
- 普段の状況などと比較できること
- 情報がつながっていること
サーバの情報を確認したところで,これらの3つの条件を満たしていないと,原因を解明することは困難です。
定量的であるということは,数値で表せるということです。「いつもより遅い気がする」といった感覚で判断してはいけません。
比較できるということは,「普段と障害時」「去年の高負荷時と今年の高負荷時」といったように,分析をするために比較対象の情報を持つことです。分析の理由によって,比較の対象となる情報が異なります。
つながっているということは,「複数の情報を組み合わせられる」ということです。たとえば,データベースサーバのSQL実行数が増えたときに,Javaアプリケーションへのリクエストが増えたためにSQLの発行回数が増えたのか,1回あたりのリクエストでのSQLの発行回数が増えたのかがわかりません。SQLの実行数に加え,Javaアプリケーションのアクセスログを組み合わせることではじめて,正確に分析できるようになります。
今回の例では,Javaアプリケーションのアクセスログを記録し,レスポンスを返せているかを把握していれば,リクエスト数が増えていることに気づけたでしょう。しかし,同じような環境では「前段のWebサーバで情報を取得しているから」という理由で,Javaアプリケーションのアクセスログを取得していないシステムが私の経験上では多いです。Webサーバへのアクセス数とJavaアプリケーションへのアクセス数が等しくならないことを把握している場合には判断を誤ることはありませんが,問題が発生したときに必ずしも有識者がいるとは限らないため,注意が必要です。
次回以降も,「問題の発生に備えて,事前にどのような対応をしておくべきなのか」「問題発生時に何をしなければならないのか」という視点から,Javaアプリケーションを運用するためのポイントを紹介していきます。