HTTPが200でも処理は止まる:監視と通知を5ケースで試した
Webの応答、仕事の完了、通知の到達、人の対応は別々に確かめる。HTTP 200だけでは、定期処理が今日も動いたかまでは分からない。
この区別を確かめるため、2026年9月14日にローカルの模擬サーバーで5ケースを実行した。実際のVPSやメール、Slackには接続していない。
三つの応答を意図的に変えた
127.0.0.1だけで待ち受けるサーバーに、HTTPの健康状態、定期処理の鮮度、通知受付の三つの模擬経路を作った。処理の鮮度はフラグで変えたもので、実際のジョブ履歴を測ったものではない。
表が画面に収まらない場合は、表を横にスクロールして確認できる。
| ケース | 健康状態 | 処理の鮮度 | 通知先の応答 | 模擬受信先に記録 |
|---|---|---|---|---|
| 正常 | 200 | 200 | 204 | 1件 |
| HTTPの障害 | 503 | 200 | 204 | 1件 |
| 通知先も障害 | 503 | 200 | 503 | 0件 |
| HTTPは正常・処理は古い | 200 | 503 | 204 | 1件 |
| 両方が復旧 | 200 | 200 | 204 | 1件 |
各観測で1回だけ通知を送る実験とし、状態変化による通知抑制や再送は実装していない。初回正常時にも受付を試した。全部で5回試し、模擬受信先が受け付けたのは4件だった。
通知先が503の行では、障害を検知しても受信記録は増えなかった。「送信を試した」と「相手が受け付けた」を同じ成功ログにすると、この失敗が埋もれる。
一方、204を返した4件も、人が読んだことの証拠ではない。今回の実験では全件、人による確認は未実施である。
healthcheckに任せる範囲を決める
Docker Composeのhealthcheckは、指定したコマンドの結果からコンテナの健康状態を確認する設定だ。そのテスト内容が浅ければ、業務の停止を見逃す。
コンテナ内からlocalhostへ接続するテストで、外部からのDNS・TLS・ファイアウォールまで確認したことにはならない。起動の依存関係はComposeの起動とhealthcheckで扱っている。起動した後に運用者が異常を知る経路は、続く2つの節で決める。
定期処理なら、最後に成功した時刻を置く
たとえば毎朝の集計を扱うなら、サーバーのトップページが開くかとは別に「対象日の集計が完了したか」を監視する。試行開始の時刻だけ更新されると、途中で失敗していても新しい記録に見える。
記録票には次の項目を用意する。期限や回数はこのサイトが一律に決めず、処理の予定と業務への影響から決める。
| 記録するもの | 誰が判断に使うか |
|---|---|
| 対象の処理名と予定 | 保守担当が未実行を見つける |
| 最後に成功した対象期間・時刻 | 業務担当がデータの古さを確かめる |
| 失敗・遅延とする条件 | 監視担当が通知するタイミングを決める |
| 通知送信の結果と再送の上限 | 保守担当が配送失敗を区別する |
| 担当が受け取った記録 | 不在時の引継ぎ先が対応状況を知る |
| 再開後の未処理分 | 業務担当が抜けを確認する |
APIの鍵や顧客データそのものを通知文に入れる必要はない。固定の処理名、異常の種類、管理者だけが見られる記録の場所で足りるかを検討する。
監視する機械まで止まった場合
同じVPS内にアプリと監視を置くと、VPS全体の停止時には監視からも連絡できない。外部の監視を使うなら、監視先の到達だけでなく、そのサービスの通知経路と担当者の受信を別に試す。
夜間に通知を受ける人がいないのなら、その時間の復旧を約束する運用にはできない。通知先を増やす前に、対応可能な時間、代理担当、業務側へ伝える窓口を決める。契約上どこまで頼めるかは管理サービスの担当範囲で照合する。
実験コードと、まだ試していないこと
Pythonスクリプトと5ケースの記録を公開する。Python 3の標準ライブラリだけを使う。新しいフォルダへ保存してpython3 run.pyを実行すると、空いているloopbackポートを使用し、終了時に閉じる。外部の通知先や認証情報は不要だ。
実験には、本番向けのタイムアウト設計、再送、重複抑制、通知のエスカレーションは含めていない。インターネット越しの通信断や、外部監視サービスが止まるケースも未検証。表は「監視を導入済み」とする証明ではなく、運用開始前に分けて試す項目の見本である。
異常に気づいた後の作業は復元を試した記録へ。毎日の処理自体をどこで動かすかは定期実行の置き場所で確認できる。
公式資料の確認日・ローカル実行日: 2026年9月14日。