Ichizokuは日本唯一のSentry公認販売業者です。
日本語のドキュメント、動画、サポート窓口で日本のお客様のSentry活用を支援します。

ダウンタイムの一般的な原因とウェブサイト監視のメリット

Article by: Lewis D.

 

本ブログの内容

  • どの Sentry 機能が使用されているのか
  • ウェブサイト監視による過負荷の検出
  • アップタイム監視による不良デプロイの検知
  • アップタイム監視による依存関係問題の検知
  • なぜアップタイム監視だけではセキュリティ脆弱性を検知できないのか
  • ユーザーに指摘される前にダウンタイムのアラートを受け取る

 


 

ダウンタイムは、最も都合の悪い瞬間に発生します。例えば、「クイックデプロイ」の直後や、思い切って5分間離れた時などです。トラフィックの急増によってエンドポイントの一つが集中的にダウンし、他のエンドポイントもダウンしてしまうかもしれません。あるいは、自信を持って本番環境に直送した「小さな変更」が原因かもしれません。

どちらの場合も、ユーザーはサイトにアクセスできず、現在は本番環境でライブデバッグを行っています。

この記事では、基本的なウェブサイト監視によって、ステータスページの更新、Slack の通知、ツイートなどの前に、より早く問題を発見できる方法を解説します。シンプルな Node.js Express アプリを用いて、監視によってパターンやボトルネックが明らかになり、ひょっとするとコーヒーを飲み終える時間を稼ぐことができる方法をご紹介します。

本題に入る前に少し余談ですが、物事をシンプルにし、完全に理論的な話にならないようにするために、基本的な Node.js Express アプリを立ち上げ、完全なエンタープライズ監視スタックにすることなく、実用的な監視機能だけに接続しました。

私が設定した内容は次のとおりです。

  • Sentry トレーシングなので、何かが壊れたときにアラートが届きます。
  • ソース マップは Sentry Wizard 経由でアップロードされます。縮小されたスタック トレースは最悪だからです。
  • アプリを軽量ホスティングサービスに投入
  • Sentry にアップタイム監視アラートを作成しました。これは、パブリックエンドポイントにpingを送信し、応答が停止した場合にアラートを出します。トレーシングとは別に動作するため、アプリがエラーを投げていなくても、全く応答していない状態を検知します。

 

 

どの Sentry 機能が使用されているのか

この記事で紹介する Sentry のすべての機能とその役割を簡単にまとめたマップを以下に示します。

特徴

監視対象

以下に使用されている箇所

アップタイム監視

パブリックURLまたはエンドポイントにアクセスできるかどうか

エンドポイントによってサイト全体がクラッシュしたときに、最初のアラートが出され、その後、別の分離されたエンドポイントルートに対してアラートが出されます。

エラー監視

処理されない例外とログに記録されたエラー

不適切なデプロイ後に発生した パッケージ欠如によるスタックトレース と、SQLインジェクションによる全損の例 を検知します。

パフォーマンス監視

各トランザクションのレイテンシ

エンドポイントに設定したp75トランザクション継続時間アラート (300 ms) を稼働させ、パフォーマンスのリグレッションを検知できるようにします。

トレーシング

エンドツーエンドで機能とサービスを網羅

遅いエンドポイントトランザクションからフレームグラフにジャンプして、再帰呼び出しが CPU を独占していることを確認できるようにします。

 

これらをレイヤーとして考えてみましょう。アップタイム は「何か問題がある」ことを伝え、エラーまたはパフォーマンス は「何が問題だったか」を伝え、トレーシング はそれがコールスタックの「どこにあるのか」を示します。

 

 

ウェブサイト監視による過負荷の検出

過負荷は Web アプリに実行させたいタスクがサーバーのハードウェアのリソースを過度に消費する場合に発生します。多くのチームがソフトウェアの複雑さに合わせてハードウェアを拡張するのに苦労しているため、これはダウンタイムの最も一般的な原因の一つとなっています。

次のシナリオを考えてみましょう。

私たちの Node.js Express アプリには /overload というエンドポイントがあります。このエンドポイントは、次のフィボナッチ関数の形で CPU 負荷の高い計算を要求します。 

注意:この例ではオーバーロードを示しているため、コードは意図的に非効率的であり、多くのスマート冷蔵庫よりもリソースが少ないサーバー上でホストされています。

アプリは無料の軽量サーバーでホストされているため、このエンドポイントに同時にアクセスする接続が少しあるだけで、アプリ全体がクラッシュしてしまいます。

しかし Sentry でアップタイム監視アラートを有効にしているため、アプリがダウンしたことをすぐに通知で受け取り、調査を開始することができます。

Screenshot from Sentry showcasing the downtime alert, pointing out the "Downtime detected" title.

ダウンタイムアラート

 

この場合、私たちはハードウェアの制限に突き当たりました。Sentry の監視ダッシュボードを見ることでアプリがタイムアウトしていることは分かりますが、Sentry はホスティングサービス上の RAM に何が起きているかまでは知ることができません。そこで私たちはそこにログインし、なぜアプリ全体がダウンしたのかを調べます。

Example from the hosting service of what it looks like when their memory limit is exceeded.

メモリ超過

 

では、これをどうやって修正するのでしょうか?アプリを再び稼働させるには、単純に電源を切って入れ直すだけで済みます。しかし、これでは将来同じことが起こるのを防ぐことはできません。

オーバーロードに対処する方法は 2 つあります。

  • アプリに割り当てられるリソースを増やす
  • タスクに必要な計算量を減らす

 

多くの場合、最も速く簡単な解決策はアプリのリソースを増やすことです。例えば、ダイナミックなサーバー環境でいくつかのスライダーを動かしたり、利用しているウェブホスティング業者に料金を支払ってアプリを上位のハードウェアに移してもらうことができます。もし自分たちでサーバーを管理しているなら、ハードウェアをアップグレードする選択肢はいくらでもあるでしょう。

しかし、これらすべての選択肢には共通点がひとつあります。費用がかかるということです。

ハードウェアが安価になるにつれて、アプリの基本的なパフォーマンスを改善するよりも、非効率なコードを動かすために強力なリソースに頼るほうが簡単になってきます。1960年代の月面着陸で使用されたアポロ誘導コンピュータには、利用可能な RAM が 100 KB 未満しかありませんでした。

では、2025年の私たちは、十分にスマートなトースター上でコードを動かすために、数か月もかけて最適化に取り組むべきなのでしょうか? それは、トースター向けの Web アプリを開発しているかどうかによります。結局のところ、すべてのプロジェクトには固有の要件があり、最も重要なのは、やみくもにリソースを割り当てて予期せぬ請求に直面する前に、自分たちの製品のスケーラビリティを理解しておくことです。

今回の例のアプリの場合、フィボナッチ数を待ち望んでいる切実なユーザーがいるとは考えられないため、問題にリソースを追加投入するのは意味がありません。

そこで代わりに、ソフトウェア的な解決策を考えてみましょう。

 

パフォーマンスアラートの設定

まず、 Sentry の設定トランザクション継続時間アラートを追加し、今後再びエンドポイントのパフォーマンスが悪化した場合に確認できるようにします。

パフォーマンスアラートの設定

 

 

この例では、しきい値を p75 で 300ms に設定しています。つまり、トランザクションの 25% が 300ms を超える場合に Sentry がアラートを出します。Sentry でのメトリクスの追跡について詳しくは、パフォーマンスメトリクス ドキュメントを参照ください。

Screenshot from Sentry pointing out the test performance alert that got triggered due to the p75 threshold exceeding 300ms.

パフォーマンスアラート

 

このアラートを受け取ったとき、クリックして詳細を確認できます。ここでは、/overload エンドポイントへの平均トランザクションが 1 分以上かかっていることが分かります。

Screenshot from Sentry showing the details of the previously mentioned test alert.

過負荷パフォーマンスメトリック

 

express-rate-limit パッケージを使ってコードにレートリミッターを追加することで、システム負荷を軽減しようとすることができます。以下のレートリミッターは、/overload エンドポイントへのリクエスト数をサーバーが処理できる範囲に制限するのに役立ちます。

アプリで最初に直面するボトルネックはメモリであるため、元の再帰的アプローチではなく、次の反復的アプローチを使うようにフィボナッチ計算機を変更することもできます。

反復処理とレートリミッターを導入することで、リソースの割り当てを拡張することなくアプリを安定させられるはずです。

 

 

アップタイム監視による不良デプロイの検知

ハードウェアに原因がない場合、ダウンタイムの原因はしばしば「自分の机の椅子とモニターの間」にあるものです。すべての開発者は人的エラーに直面し、そのコーディングミスの複雑さはさまざまです。

上記のサンプルアプリを作成している際にも、そうしたエラーのひとつに遭遇しました。/overload エンドポイントにレートリミッターを追加する際、アプリを Web ホストサーバーにデプロイするためのリモートリポジトリに express-rate-limit パッケージを含めるのを忘れてしまったのです。ローカルでは問題なくコードを実行できましたが、この見落としにより、アプリをクラウドにデプロイした際にエラーが発生しました。

Sentry の監視がなければ、Web ホストは汎用的なデプロイ失敗メッセージを表示し、以前に動作していたコミットにロールバックするだけでした。これは便利なリカバリ機能ではありましたが、アプリケーションに何が起きたのかについての情報はまったく得られませんでした。幸いなことに、Sentry は詳細なエラーメッセージを提供してくれたため、問題がすぐに明らかになり、必要なパッケージをインストールした上でアプリを再デプロイすることができました。

Sentry screenshot showing the detailed "package not found" error message in the stack trace.

パッケージが見つかりません

 

このサンプルアプリは単純なため、コーディングエラーも簡単に修正できます。しかし、解決の難易度はアプリケーションの複雑さに比例して指数関数的に高くなり、ダウンタイムを減らすためには監視ツールを導入しておくことが極めて重要になります。

 

 

アップタイム監視による依存関係問題の検知

多くの Web アプリケーションは、コア機能を提供するために外部サービスに大きく依存しています。開発者は、何年も使っているサービスは無期限に安定して動作し続けると誤って想定してしまうことがよくあります。しかし残念ながら、これは常に当てはまるわけではなく、依存関係の不備によってアプリが致命的な影響を受けることもあります。

この問題をシミュレートするために、サンプルアプリに次の /dependency-issue エンドポイントを追加します。

このエンドポイントは axios ライブラリを使ってサードパーティサービスから結果を取得します。ここではサービスとして API シミュレーターを使用し、返却値を制御できるようにしています。

次に、この API シミュレーターを設定して、GET リクエストに対して 500 エラーを返すようにします。エンドポイントにアクセスを試みると、次のエラーメッセージが表示されます。

Dependency issue: Third-party service is down

しかし、アプリの残りの部分は正常に動作しています。

残念ながら、先ほどの実験で設定したアップタイムモニターはこの問題ではトリガーされません。なぜなら影響を受けているのは /dependency-issue エンドポイントだけだからです。これが、アプリケーションのすべての一般的なエンドポイントに対して複数のアップタイムモニターを有効にすることを推奨する理由です。

モニタリングがなければ、上記のエラーメッセージだけを頼りにアプリをデバッグすることになります。そこで /dependency-issue エンドポイントを指す新しいアップタイムモニターを追加すれば、少なくともサードパーティ API が再びダウンした場合に早期警告を受け取ることができます。しかし、エラーに関するさらなる情報を得るには、Sentry の nodeProfilingIntegration を使った追加モニタリングを設定する必要があります。

この設定を行うと、問題のあるエンドポイントにアクセスしようとした際に、即座に Issue アラートを受け取ります。

Sentry screenshot showing the issue alert, pointing out the 500 error exception under the "Breadcrumbs" section.

Axios エラー

 

注意深い人は、429 エラーも発生していることに気づいたかもしれません。

このエラーは、アップタイムモニターが継続的にポーリングを行った結果、API シミュレーターへの無料コール枠をすべて使い果たしたために発生しました。アップタイムモニターは設定されたエンドポイントに対して非常に軽量なコールを行うため、実際のアプリケーションにおいては通常問題にはなりません。とはいえ、アップタイム監視はアプリケーションに負荷を与えることになるため、その影響を考慮する必要がある点は覚えておくべきでしょう。

依存関係の問題を修正するのはそう簡単ではありません。サードパーティの依存関係を利用することは本質的にリスクがあり、アプリケーションの一部の制御を相手に委ねることになるからです。その見返りとして、その機能の作成と維持の責任も相手に委ねることになります。この見返りはしばしばリスクを上回るため、多くのモダンなアプリケーションは数十、場合によっては数百ものサードパーティ依存関係を持っています。もし特定のサービスがアプリケーションにとって信頼できないことが明らかになった場合、別のサービスプロバイダーに切り替えるか、自分たちでサービスの独自実装を行って制御を取り戻すことを検討する必要があるでしょう。

 

 

なぜアップタイム監視だけではセキュリティ脆弱性を検知できないのか

ここからは少し面白い例です。アプリのダウンタイムが、あなた自身でも、ハードウェアでも、サードパーティのサービスプロバイダーでもなく、別の原因によって引き起こされるケースがあります。娯楽目的や金銭目的で、悪意ある存在があなたのアプリケーションを破壊しようと狙う場合です。

最も一般的なのは、分散型サービス拒否(DDOS)攻撃の形をとるもので、攻撃者がボット接続を使ってエンドポイントを洪水のように埋め尽くし、通常のユーザーにとってアプリを無力化してしまいます。実際には、これは最初の例で示したオーバーロードしたサーバーとよく似ています。攻撃によるダウンタイムなのか、通常利用によるオーバーロードなのかを判別することは可能ですが、必要となる対策は似通っています。すなわち、監視・負荷分散・レート制限です。

次の例では異なるシナリオを探るため、最悪の種類の SQL インジェクションに対して脆弱なアプリを作成しました。

次のようなシンプルな計算機アプリを作成したとします。

Screenshot showing he aforementioned calculator app, with a regular calculator up top, and a fibonacci calculator at the bottom.

電卓アプリ

 

しかし、あなたはユーザーが計算を 1 回しかできないようにすることにしました。個々のユーザーが同じ計算を繰り返さないようにするために、入力された計算式とそのユーザーの IP アドレスを MySQL データベースに保存します。

「Calculate」ボタンが押されるたびに、データベースを照会してその計算がすでに実行されているかどうかを確認し、もしそうであればユーザーにエラーを表示します。

An error message is highlighted in the calculator app, showing a "calculation already performed" error.

電卓アプリのエラー

 

/calculate エンドポイントが呼び出されたとき、次のコードを使ってユーザーが以前にその計算を入力したことがあるかどうかを確認できます。

残念ながら、攻撃者はあなたのコードに脆弱性があることに気づき、次のような HTTP リクエストを仕掛けてきます。

http://MyFirstWebApp:4000/calculate?operation=add%27%3B%20DROP%20TABLE%20Calculations%3B%20--&num1=5&num2=3

サーバー側では、これは次の SQL ステートメントに変換されます。

この状態でサーバー上で計算をしようとすると、Error: Failed to check existing calculation というエラーが表示されます。幸いなことに、あなたの電卓アプリはサンプルアプリ上に構築されており、Sentry のウェブサイト監視機能が組み込まれています。そのため、災害が発生したことを知らせるアラートを受け取ります。

An issue in Sentry showing the "Table doesn't exist" error.

テーブル消失

 

テーブル内にあったデータを回復する方法はありません。もし実際のユーザーと価値のあるデータを扱うアプリケーションを運営していたなら、それは開発者にとって非常に厳しい一日となったことでしょう。

この種のサーバーダウンタイムの問題のひとつは、以前に使用したアップタイムモニターのような一部の監視ツールでは、エンドポイントが利用できなくなったことを検知できない点です。エラーがデータベースレベルで発生しているため、Web アプリの視点からはエンドポイントが依然として稼働しており、正常に機能しているように見えてしまいます。これが、Web サイト監視の手法を多様化させることが重要である理由です。この例では、追加で導入していた Sentry のエラー監視が、少なくともより多くの情報を提供してくれました。

成功したサイバー攻撃は、その深刻さに応じて、回復が最も困難な問題となり得ます。今回のように、しばしばデータが回復不能になるため、アプリケーションを可能な限り安全に保つために努力を惜しまないことが重要です。例えば、攻撃者が用いた SQL インジェクション手法を防ぐために、次のようなパラメータ化クエリを使用することができました。

サイバーセキュリティはイタチごっこのようなものであり、これから悪用されるかもしれないすべての脆弱性を知ることは決してできません。そのため、アプリケーションの重要性に応じて強化される災害復旧計画を策定しておくことが極めて重要です。

 

 

ユーザーに指摘される前にダウンタイムのアラートを受け取る

Web サイト監視はあなたのアプリを修復してくれるわけではありませんが、壊れ始めたときにそれを知らせてくれます。そして正直なところ、それは戦いの半分です。時間を稼げるのです。掘り下げる時間、デバッグする時間、サポートチケットが殺到する前に修正する時間を。

とはいえ、すべてを検知できるわけではありません。より深い監視やトレーシングの代わりにはなりません。しかし、広範なオブザーバビリティ実践と組み合わせれば、確かな第一の防衛線となります。

Sentryの Web サイト監視実際にご覧になりたい方は、ブログでさらに多くの例をご用意しています。セットアップは想像以上に簡単なので、ぜひご自身でSentryを試してみてください。そして、実際に使ってみてフィードバックがありましたら、GitHubに投稿するか、 Discordで(優しく)声をかけてください。ご意見をお待ちしております。

 

 

Original Page: Common Downtime Causes and How Website Monitoring Can Help

 

 




IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談はこちらのフォームからお気軽にお問い合わせください。

 

シェアする

Recent Posts