HTTPの診断
目標
HTTPの応答を、ステータスコード・ヘッダー・タイミング・本文の4つの軸に分けて読み、それをヘルスチェックスクリプトにまとめます。
なぜ重要なのか
「応答が遅い」という報告を受けたときに必要なのは、より多くのダッシュボードではなく、1つのリクエストの時間を区間ごとに分解して見ることです。curl -wのタイミング変数は、名前解決 / TCP接続 / TLS / サーバーの最初のバイト / 本文の転送を、それぞれ教えてくれます。time_connectまでは正常なのに、time_starttransferだけが大きければ、ネットワークは無実で、アプリケーションが犯人です。その場で論争が終わります。そして、ヘルスチェックには必ず最大待ち時間をかける必要があります。ないと、相手が応答しないときにスクリプトが永遠に止まり、cronがそれを5分ごとに起動すると、プロセスが溜まります。
ステップ
/root/wwwをドキュメントルートに、/root/httpを作業ディレクトリとして使います。
/root/www/index.htmlを作ってlabhub-http-okを入れ、python3 -m http.server 8000 --bind 127.0.0.1 --directory /root/wwwをバックグラウンドで起動した後、PIDを/root/http/server_pid.txtに書いてください。- 存在しないパスをリクエストしたときのステータスコードを、
/root/http/status404.txtに、数字だけで書いてください。 /index.htmlの応答ヘッダーだけを受け取って、/root/http/headers.txtに保存してください。本文が混ざってはいけません。- リクエストの
time_namelookup、time_connect、time_totalの3つの値を、空白で区切って1行で/root/http/timing.txtに保存してください。 /root/www/api.jsonを作ってください。nameはlabhub、tagsは値が2つ以上の配列である必要があります。そして、そのファイルをサーバーから受け取って、tagsの2つ目の値を、/root/http/tag.txtに書いてください。/root/www/subディレクトリを作って、ファイルを1つ入れてください。http://127.0.0.1:8000/subを、リダイレクトをたどらずにリクエストしたときと、たどったときのステータスコードを、/root/http/redirect.txtに、次の2行で書いてください(プレースホルダーはステータスコードです)。no_follow=<코드>follow=<코드>
- POSTリクエストを送ったときのステータスコードを、
/root/http/method.txtに、post=<코드>の形式で書いてください(プレースホルダーはステータスコードです)。 /root/http/healthcheck.sh <URL>を作ってください(プレースホルダーは、ステータスコードと秒数です)。- 2xxなら、
ok code=<코드> time=<초>を出力して、終了コード0で終了します - 応答は来たが2xxでなければ、
down code=<코드>を出力して、終了コード1で終了します - 接続そのものができなければ、
downで始まるメッセージを出して、終了コード1で終了します。10秒以内に判定する必要があります。
- 2xxなら、
参考
curl -s -o /dev/null -w '%{http_code}' URLでステータスコードだけを取り出します。接続失敗時には000が出ます。curl -sI URLは、HEADリクエストでヘッダーだけを受け取ります。curl --max-time 5で、最大待ち時間をかけます。- よくある間違い1: ステップ6で、
-Lなしでも200が出るなら、末尾にスラッシュを付けてリクエストしたのです。スラッシュなしでリクエストして初めて、301が出ます。 - よくある間違い2: ステップ8で、
000を数字としてだけ比較すると、接続失敗と正常を区別できません。
ローカルHTTPサーバーを起動する
/root/www/index.htmlを作ってlabhub-http-okを入れ、python3 -m http.server 8000 --bind 127.0.0.1 --directory /root/wwwをバックグラウンドで起動した後、PIDを/root/http/server_pid.txtに書いてください。
python3 -m http.serverに、ドキュメントルートを指定するオプションがあります。127.0.0.1にだけバインドしてください。
ステータスコードだけを取り出す
存在しないパスをリクエストしたときのステータスコードを、/root/http/status404.txtに、数字だけで書いてください。
本文を捨てて、ステータスコードだけを出力する-w変数があります。
ヘッダーだけを受け取る
/index.htmlの応答ヘッダーだけを受け取って、/root/http/headers.txtに保存してください。本文が混ざってはいけません。
HEADリクエストを送るオプションです。本文がファイルに混ざってはいけません。
区間ごとの所要時間を測る
リクエストのtime_namelookup、time_connect、time_totalの3つの値を、空白で区切って1行で/root/http/timing.txtに保存してください。
-wのtime_namelookup、time_connect、time_totalの3つを、空白で区切って1行で出力してください。
JSONの応答から値を取り出す
/root/www/api.jsonを作ってください。nameはlabhub、tagsは値が2つ以上の配列である必要があります。そして、そのファイルをサーバーから受け取って、tagsの2つ目の値を、/root/http/tag.txtに書いてください。
curlの出力をjqに渡します。配列のインデックスは0からです。
リダイレクトをたどる
/root/www/subディレクトリを作って、ファイルを1つ入れてください。http://127.0.0.1:8000/subを、リダイレクトをたどらずにリクエストしたときと、たどったときのステータスコードを、/root/http/redirect.txtに、次の2行で書いてください(プレースホルダーはステータスコードです)。
no_follow=<코드>follow=<코드>
curlは、デフォルトではリダイレクトをたどりません。ディレクトリのパスに末尾のスラッシュがないと、サーバーが301を返します。
未実装メソッドの応答
POSTリクエストを送ったときのステータスコードを、/root/http/method.txtに、post=<코드>の形式で書いてください(プレースホルダーはステータスコードです)。
-Xでメソッドを指定します。このサーバーは、GETとHEADだけを実装しています。
ヘルスチェックスクリプト
/root/http/healthcheck.sh <URL>を作ってください(プレースホルダーは、ステータスコードと秒数です)。
- 2xxなら、
ok code=<코드> time=<초>を出力して、終了コード0で終了します - 応答は来たが2xxでなければ、
down code=<코드>を出力して、終了コード1で終了します - 接続そのものができなければ、
downで始まるメッセージを出して、終了コード1で終了します。10秒以内に判定する必要があります。
正常・2xx以外・接続不能の3つを区別する必要があります。最大待ち時間を必ずかけてください。