大和田尚孝『システムはなぜダウンするのか』日経BP社、2009年1月

システムはなぜダウンするのか

システムはなぜダウンするのか

■内容【個人的評価:★★★★−】
○まえがき

  • システムがダウンする原因は、機械の故障、ソフトウェアの不具合、操作ミス、アクセス量の急増などさまざまです。しかもたいていは、ひとつの不具合が別の不具合を引き起こし、複数の不測の事象が数珠繋ぎに発生します。原因を順におっていくのは難しくありませんが、ダウンの発生状況から根本的な原因までさかのぼるのは、たとえるなら警察が事件現場から真犯人を見つけ出すような難しさがあります。

○第一章「システムが止まった・・・ −ダウンとは何か」

  • ダウンとは、システムが本来の役割を果たせていない状態を指します。
  • さらに本書では、異常な動作をしたり、誤った処理をしたりする誤作動も、一部はダウンとして取り扱うことにします。
  • システムは、あらかじめ決められたとおりに繰り返し動作するのは得意ですが、いったん異常な動作を引き起こしてしまうと、どんどん悪化する傾向があります。
  • 例外ルートの処理は正常ルートに比べて、実際に実行される回数が極端に少ないということです。このため、バグが残っていたとしてもなかなか表面化しません。
  • 結局のところ、絶対ダウンしないシステムは作れません。それどころか、むしろ今後は、ダウンの回数は増えていくと思われます。システムの複雑化・大規模化が進んで、ますますプログラムにバグが紛れ込みやすく、同時に除去しにくくなるからです。
  • システムの処理能力を高めるために、価格性能比に優れた最新技術を積極的に使うケースも増えています。ダウンのリスクは高まりますが、それ以上にメリットがあるという考え方です。
  • ダウンは最新技術を使うこととのトレードオフという一面があることも知っておきたいところです。
  • ダウンを100%なくすのではなく、ダウンしてもすぐに復旧させる、ダウンした際の影響範囲を小さくする、同様のダウンが起きないように対策を講じる、といったアプローチが求められます。
  • ダウンが起きたら、まずは影響範囲の把握と応急処置が第一です。被害を最小限に食い止めるには、一秒でも早くシステムを復旧させなければなりません。復旧の次に取り組むのが、ダウンの根本的な原因を突き止めることです。応急処置だけでは、また同様のダウンが起きてしまう可能性があります。再発を防ぐには、原因を突き止めて再発防止の手を打たなければなりません。ダウン対応でもっとも難しいのは、じつはこの原因究明の作業です。複数の異常が連鎖して発生するということは前述のとおりです。ダウンから根本原因を探るには、この連鎖を遡っていく必要があります。
  • 根本的な原因さえわかれば、対策を打つのは、それほど難しくありません。技術者にとっての腕の見せどころは、いかに原因を迅速に突き止められるかです。それにはまず、システム全体のハード構成やネットワーク構成、使用するOSやミドルウェアの知識、アプリケーションの仕様、開発言語の知識などをすべて理解している必要があります。それだけではなく、直近でシステムに何らかの修正を施したか、運用手順に問題はなかったか、ダウンした日は普段とは異なる特別な処理を実施する日だったなど、システムを取り巻く外的変化や変更履歴、運用状況などもおさえておく必要があります。優秀な技術者ほど、ダウンの発生状況や影響範囲などから根本原因を突き止める嗅覚があると言われるのは、こうした幅広い知識を身に付けているからです。ダウンの原因を突き止めることができるようになると、そのスキルを設計段階に活かせるようになります。
  • ダウンの原因は千差万別ですが、大きく四つのグループに分けられます。
    • 1ソフトウェアの不具合
    • 2性能・容量不足
    • 3設定・操作ミス
    • 4不慮の事故
  • ダウンの状況には原因のヒントが隠されている。

○第二章「きちんとテストしたはずなのに・・・ −アプリケーション・ソフトの不具合」

  • テストの種類と開発フェーズ(V字モデル)
  • ・要件定義→
    • 受け入れテスト:システム全体が要求どおりに作られているか
  • ・基本設計(機能設計、性能設計、運用設計)→
    • 運用テスト:実際に運用できるか
    • 障害テスト:障害から復旧できるか
    • 負荷テスト:アクセス集中や連続運転に耐えられるか
    • 回帰テスト:変更対象外の機能が正常に動作するか
    • 機能テスト:基本設計書の機能を実現できているか
  • ・詳細設計→
    • 結合テスト:プログラム間のデータの受け渡しに問題はないか
  • ・プログラミング→
  • テストシナリオは、大規模なシステムであれば1万件を軽く超えます。メガバンクのシステム統合ともなれば、100万件にも達します。
  • 必要なデータを誤って削除したときのために用意しておいたデータ復旧プログラムにバグがあり、データを復旧するどころか全データを削除してしまったー。作り話のようですが、実際にあったトラブルです。
  • 過半の処理が正常に実行されていると、意図的に他行取引を停止するという判断も下せません。一部の処理が異常終了するものの、完全に停止しているわけではない。こういった不安定な状態がもっとも対処に困るのです。原因の究明にも手を焼きます。
  • トランザクション処理は、原子性、一貫性、独立性、耐久性という四つの特性を必ず確保する決まりがあります。
  • もし、トランザクション処理の途中で異常が発生したら、途中まで進んだすべての更新処理を元に戻します。これをロールバックといいます。すべての処理が完了してから処理結果を確定することをコミットといいます。
  • デッドロックが起こるのは、複数のトランザクション処理で、データベースのアクセス順序が異なるからです。すべて同じ順序にしておけば、ロックが交差することはありえないはずです。

○第三章「アプリケーションだけではない・・・ −OS、ミドルウェアの不具合」

  • 高い信頼性が求められるシステムでは、サーバー一台だけで動作させることはありません。動作中の本番系サーバーとは別に、予備の待機系サーバーを用意するのが一般的です。本番系は運用系などと表現することもありますし、待機系は予備系などと定義することもあります。本番系で異常を検知したら、待機系が処理を引き継ぎます。
  • このように一台が故障しても他のサーバーが処理を代替できるシステム構成を冗長構成あるいはシステムの冗長化と言います。冗長化によりシステムのダウンを減らすことを可用性を高めると表現します。
  • 冗長化構成の分類
    • (1)負荷分散クラスタ(複数台で分散して処理。一台が故障したら残るサーバーがその後の処理をすべて担当する)−オープン系サーバーで構築したシステムのWeb/アプリケーション・サーバー
    • (2)デュプレックス(1台が本番系として稼働。待機系は故障時に処理を引き継ぐ)−メインフレームで構築したシステム
    • (3)デュアル(二台が同じ処理を重複して実行。相互に結果を比較して同期をとりながら全く同じ状態を保つ。一方が故障しても片方だけで処理を継続できる。)−軍事システムなど人命にかかわるシステム
  • 負荷分散クラスタは、複数台のサーバーで処理を分担します。1分間に100件のトランザクション処理を受信するシステムでサーバーが二台あったら、それぞれが50件ずつ処理するイメージです。ただ、必ずしも2台のトランザクション数が均等になるように振り分けるラウンドロビン方式とは限りません。たとえば、二台のうち応答時間が短い方にトランザクション処理を振り分ける最短応答時間方式、サーバーの負荷がかかっていない方に振り分ける最小サーバー負荷方式、などの方式もあります。いずれの振り分けかたにせよ、二台が別々のトランザクション処理を受け持つことでお互いの負荷を軽減するという仕組みは共通です。各サーバーに処理を振り分けるには、負荷分散装置(ロード・バランサ)と呼ばれる機器を使います。
  • 二台のうち一台が故障すると、残るサーバーが、その後の処理をすべて担当します。ロード・バランサは、故障したサーバーには処理を振り分けません。
  • いずれの構成でも、待機系に処理を引き継ぐには、まず本番系の異常を検知しなければなりません。これは前述のとおりOS やミドルウェアの役目です。ところがソフトウェアの不具合により、故障したハードウェアやソフトウェアが出力したダイイング・メッセージを検知できなかったり出力できなかったりすることがあります。
  • クラスタ・ソフトと呼ばれるミドルウェアの不具合もあります。クラスタ・ソフトとは、主にホットスタンバイ(HAクラスタ)構成を組んだサーバーの切り替えを制御するソフトウェアです。いずれかのサーバーが故障したときに、別のサーバーに処理を引き継ぐ重要な役割を担います。クラスタ・ソフトは、HAクラスタ構成を組んだサーバーのそれぞれで動作します。お互いに正常に動作しているかどうかを定期的に確認しあうのです。具体的には、ハート・ビートと呼ぶ信号を出しあうことで稼働状況を把握します。待機系が本番系とのハート・ビートが途絶えたことを感知すると、本番系から処理を引き継ぎます。
  • ところがクラスタ・ソフトに不具合があり、待機系がハート・ビートの途切れを検知できませんでした。このため、引き継がれるはずの処理が本番系のサーバー内で滞留したままになりました。追い討ちをかけるように、停止した本番系サーバーにアクセス要求が次々に舞い込み、すべての要求がタイムアウトとなりました。スタンバイ中だった待機系サーバーに切り替わることなく、データベース・サーバーが全面ダウンしてしまったのです。
  • OSやミドルウェアの不具合は、稼働前のテストで見つけるのがきわめて難しいと言わざるを得ません。サーバーの内部部品やソフトウェアの一部機能に障害を意図的に発生させて、正しく検知できるか、処理を引き継げるかを確認する障害テストをすべてのケースについて行うのが難しいからです。
  • 正常に動作しているシステムのサーバーが老朽化したので新機種に入れ替えた。新機種に搭載するOSは、それまで使っているものよりも新しいバージョンだ。このとき、事前に動作確認したにも関わらず、OSを変えたとたんにミドルウェアが正常に動作しなくなったー。こんなトラブルに直面することがあります。
  • ソフト開発ベンダーは、製品の出荷前に自社の検証センターで複数のソフトウェアとの組み合わせを検証し、動作に問題がないことを確認した上で動作OSを指定します。ところが動作OSとして指定されているにも関わらず、不安定な動作になることがあります。
  • このようなソフトウェアの組み合わせ問題は、特にオープン・システムで顕著です。それぞれの製品の開発ベンダーが異なるからです。メインフレームの場合、ハードウェアを含めて一社がすべてのソフトウェアを開発しているため、製品間の組み合わせについても動作保証を得やすい環境にあります。オープン・システムの普及は、ソフトウェアの低価格化、製品間の競争促進による高機能化というプラスの効果をもたらしました。一方で、システムの可用性の面からみると、組み合わせ問題という新たなダウンの火種を生んだのです。
  • オープン・システムでも、特定ベンダーのソフトウェアに統一はできます。それでもメインフレームのようにはいきません。同一ベンダーの製品でも、買収からしばらく経過するまでは、動作保証が得られないことがあるのです。
  • 先ほど、OSやミドルウェアは個別に開発したアプリケーション・ソフトに比べて利用者が多いことなどもあってバグが少ない、と書きました。違う言い方をすると、あまり利用されていないソフトウェアには比較的多くのバグが潜んでいることになります。
  • 新バージョンの誤作動によるダウンを防ぐには、利用者の自衛策が必要になります。たとえば金融機関は、最新バージョンをあえて使わず、1世代前の旧バージョンを購入したり、バージョンアップを控えたりします。サポート期限が迫っているのを覚悟の上での決断です。オープン系ソフトよりもサポート期間が長いメインフレーム用のソフトウェアを積極的に採用することも少なくありません。
  • 新製品の販売から期間が経過して、パッチ・ファイルの提供ペースが落ちてくると、その製品を枯れてきたと表現することがあります。枯れた製品と聞くと、マイナスのイメージを連想しますが、ソフトウェアの場合は、バグが十分に検出され高品質な製品というプラスの意味を持ちます。
  • ある世界有数のOSベンダーによると、利用者からOSの不具合ではないかと連絡があったトラブルのうち、半数近くは別の原因だったそうです。他社ソフトやアプリケーションの不具合、あるいはOSのパラメータ設定など使い方を誤ったケースが半分に上るのです。世界中の技術者が不具合の原因の切り分けに苦労していることを象徴しています。
  • 原因の切り分けが難しい例として、ここではメモリー不足を取り上げます。何らかの理由でメモリー領域が不足して処理が滞り、ダウンに繋がるというものです。
  • ある目的で使用中のメモリー領域は他の用途には割り当てません。ソフトウェアなどからメモリーの利用が終わったとの指示を受けると、使用中の状態を未使用に戻します。これをメモリーの解放といいます。使い終わったにも関わらず未使用に戻さないのがメモリーの解放漏れです。メモリーの解放漏れが続くと、次第に使える領域が少なくなるメモリー・リークが起きます。すべての領域が使用中になると、メモリーの割り当てができなくなります。これがメモリー不足です。
  • 最たる例はC言語などで開発したアプリケーションです。C言語では、プログラム内で、メモリーの確保や解放を操作できます。使い終わったメモリー領域を解放する記述を忘れると、メモリーが解放されないままになります。
  • C言語以外でも、たとえばJavaの場合、プログラムを読み込んだりするのに使うヒープ領域の割り当て領域量が少ないケースです。Javaは、プログラム内でメモリー領域の確保や解放などの記述はしません。JavaVM(Java仮想マシンJVM)と呼ぶJavaプログラムの実行支援ソフトが一括してメモリー制御を担っているからです。JVMには、使わなくなったメモリー領域を一時的に解放するガベージ・コレクションという処理があります。それでも割当量そのものが足りなければメモリー不足は起きます。
  • OSやミドルウェアに限らずアプリケーション・ソフトでも同様ですが、ソフトウェアのやっかいな点は、待機系でも同様の不具合が発生する点にあります。
  • システムの冗長化は、ハード故障には効果的ですが、ソフトウェアの不具合には効果がないのです。

○第四章「アクセス殺到に耐えきれず・・・ −性能・容量不足」

  • 大半の処理がタイムアウトになる状態とは、言い換えると、要求データの大半を処理できない状態です。こうした状態が性能不足であり、処理遅延とも呼びます。
  • 性能不足が発生したときのシステムの状態は、大きく二つに分けることができます。ひとつは、メモリーやCPU、ディスク装置など特定のハード資源が性能上の限界に達しているケースです。もうひとつは、ソフトウェアの処理性能であるソフト資源にボトルネックがあるときです。
  • システムにおいては、Web三層構造が一般的です。三層とは、パソコンから要求データを受け付けるWebサーバー、業務処理を行うアプリケーション・サーバー、データベースの更新を担当するデータベース・サーバーです。
  • Webサーバーは、パソコンとの間で接続を確立し、必要に応じてアプリケーション・サーバーに要求データを転送します。この際、Webサーバーがいくつの処理を並行でできるようにするかを決めます。この設定値がWebサーバーの同時実行数です。同時実行数とWebサーバーの台数の積が同時に受け付けられる要求データ件数ということになります。
  • アプリケーション・サーバーは、Webサーバーから要求データを受信すると待ち行列に格納し、受信順に実行します。
  • ソフト資源に最適な値を設定するのは、難易度が高い作業です。複数のパラメータをバランスよく設定しなければならないからです。たとえば、アプリケーション・サーバーの同時実行数や実行待ちリクエスト数に比べてWebサーバーの同時実行数を小さくしすぎると、Webサーバーがボトルネックになり、アプリケーション・サーバーが性能を十分に発揮できません。
  • では、すべてのソフト資源をバランスよく設定すればそれで万全かというと、そうでもありません。ハード資源の性能を最大限に生かす形で設定する必要もあります。
  • ソフト資源で注意すべき点は、システムの構築時に設定値を一度決めれば永久に万全というわけではないことです。
  • ソフト資源が原因の性能不足が発生する背景として、設定値が適切かどうか確認するためのテスト手法が確立していないことがあります。ソフト開発であれば、単体テスト結合テスト、総合テストという具合に、品質向上のための工学的なアプローチが定められていますが、ソフト資源のテスト手法はそれほど確立していません。
  • 本番システムを使って大量のアクセスをかけた負荷テストをこなすのが難しいことも、ソフト資源のテストがしにくい原因のひとつです。テスト・ツールを使えば、Webサーバーに大量のアクセスを実行するといった局所的なテストはできますが、システム全体に本番同様の負荷をかけるのは容易ではありません。こうしたテストの難しさが、ソフト資源の性能不足によるダウンを頻発させているのです。

○第五章「気づかなかったは許されない・・・ −環境設定・変更ミス」

  • 複数の会社が開発したハードウェアやソフトウェアを組み合わせて使うオープン・システムの時代になって、ソフト間のパラメータの関連を洗い出す作業の難易度が高まりました。個別の製品ベンダーは、自社のパラメータ設定の適正値については詳しく教えてくれます。ところが個別のパラメータが他社製品のどのパラメータに影響するかまでは、責任を持って教えてはくれません。システムの能力を増強したい場合に、どこのパラメータをどう直せばいいのかは、システムを利用する企業の担当者が考えるしかないのです。あるいは、システム全体の運用・保守契約をベンダーと結んで、委託先に調査や作業を依頼する必要があります。
  • ライブラリ管理は、あらかじめ定めた手順に従って進めるのが鉄則です。異例の手順をとると、必要な作業が漏れる可能性が高まるからです。

○第六章「その「うっかり」が致命傷・・・ −運用・操作ミス」

  • システムがダウンしたら、まずは一刻も早く復旧させることが最優先です。ですが、慌てすぎて復旧作業中にミスをしてしまうと、さらなる被害の拡大を招いてしまいます。このような二次災害は、なかなか減りません。しかも、過去のケースを見ても、大規模なトラブルに発展することが多いので注意が必要です。

○第七章「まさか、こんなことが起こるとは・・・ −ハード故障、不慮の事故」

  • ミラーリングは全く同じ内容のデータを二つのディスク装置に同時に書き込みます。これはディスク装置の故障からデータを守ることができる一方で、格納するデータ量の二倍のディスク容量が必要となるため効率的ではありません。そのため、データを保護しつつ、より効率的にデータを格納する方法としてRAIDと呼ぶ方式を使うケースがよくあります。RAID5ではまず、格納するデータをブロック単位に分割したうえで「パリティ・データ」を生成し、各ブロックのデータとパリティ・データを別々のディスク装置に分けて書き込みます。
  • ここで、ディスク装置の一台が故障したとします。このとき、残るディスク装置のデータとパリティ・データを使えば、消失したデータが「1」と「0」のどちらかを求められます。言い換えると、ディスク装置の一台が壊れてもパリティ・データを使ってデータを復元することが可能となります。

○第八章「障害対応は時間との闘い・・・ −ダウンに学ぶ」

  • システム・ダウンに見舞われたとき、まず何をすべきでしょうか。システムを開発した技術者ならば、「自分たちが作ったシステムのどこに問題があったのか。どうして問題が起こったのか。どう直すべきか」とプログラムのソースコードを開きたくなるのが当然です。ただし、真っ先にとるべき行動は原因の究明や誤りの修正ではありません。システムを一秒でも早く復旧させることです。
  • ダウンに至った経緯をすべて明確にした後は、同様の不具合が起きる可能性はないかシステム全体を総点検します。表面化していない部分にも同様の不具合が潜んでいる可能性があります。
  • 実際にダウンが起こると、経営層や顧客、利用部門やメディアを含めて「どうしてダウンしたのか。技術者は何をやっていたのか」と開発・運用現場を責めます。もちろん、99. 999%を目指しているからといって、年に5分は止まってもいいというわけではありません。ただ、ファイブナインに見合う投資をしたのであれば、得られるリターンはファイブナインの稼働率であって100%ではないのです。
  • ダウンをすべて悪ととらえるのではなく、むしろシステムの信頼性を高める機会を得たと前向きにとらえ、再発防止策の検討に力を注いだ方が合理的ではないでしょうか。システムの開発や運用・保守に携わる技術者は、不運にもダウンに見舞われたとしても、落ち込むのではなく転んでもただでは起きない気概を持って臨むべきです。

■読後感
この3ヶ月、ずっとシステムのダウンに見舞われてきた。なぜダウンするのか、委託先は何をやっているのか、歯がゆい思いを続けてきた。
しかし、実際には委託先も何が起こっているのかわからなかったのだ。推測はできても対処することができず、そうした中、別のシステムのダウンが相次いだ。
システムはリジッドな部分と柔らかい部分があって、今回なんとかメインのダウンが1カ月以上経ってから収束したのは、いろいろ打った手ももちろんあるけれど、システムの自己調整機能が関係している。というのも、ある日、なにもしていないのにシステムは前日までのダウン状態から回復していたのだ。
以前のバッチ系システムと比較して、Web系のシステムはDB、Webサーバ、ミドルウェア、アプリケーションとさまざまな要素が介在しており、しかも利用者とシステムが直接向かい合うために影響範囲が大きい。なにか起きたときにプロでも分からないという状況である。
事後に何を学ぶのかが大事。そのとおりで検証を続けていくことが必要だろう。少なくとも自分自身はシステムの基本構成からこの書で解説される様々な要因などいろいろ学ぶところがあった。