[Fastly] backendのhealth状態(req.backend.healthy)を監視する方法 (version 2, 全POPでのhealth状態取得)


前回までのあらすじ

少し前になりますが、下記のような記事を書きました。

上記方法の問題は、リクエストを発行したclientに最も近いPOPのhealth状態しか取得できないことでした。
では全拠点POPでのbackendのhealth状態をまとめて取得・監視する方法は無いのでしょうか?

Fastlyの /content/edge_check APIを使う

Fastlyには色んなAPIがありますが、あまり知られていないAPIの1つに、/content/edge_check があります。

これは、Fastlyの管理画面でも使える Check cache と同じですが、APIの方が確認できる情報量が少し多いです。

このAPIが何をしてくれるかと言うと、通常は引数にURLを渡すことで全てのPOPに対してそのURLがキャッシュされているかどうかをチェックし、その結果をJSONで返してくれます。

例えば、APIの出力は下記のようになります。下記はサンプルなので1POP分だけの出力を切り取っていますが、POPの数だけこれが続きます。

[
  {
    "hash": "a6fa75cf5b77f61527421aaaa4ddcd50",
    "pop": "fjr-ae",
    "response_time": 0.399193,
    "server": "cache-fjr7922",
    "request": {
      "headers": {
        "User-Agent": "Fastly/cache-check",
        "Fastly-Debug": 1,
        "Host": "<name>.global.ssl.fastly.net"
      },
      "method": null,
      "url": null
    },
    "response": {
      "headers": {
        "Server": "Varnish",
        "Retry-After": "0",
        "Content-Length": "191",
        "Content-Type": "application/json",
        "Accept-Ranges": "bytes",
        "Date": "Wed, 21 Feb 2018 07:51:53 GMT",
        "Via": "1.1 varnish",
        "Connection": "close",
        "Fastly-Debug-Path": "(D cache-fjr7922-FJR 1519199513)",
        "Fastly-Debug-TTL": "(M cache-fjr7922-FJR - - -)",
        "Fastly-Debug-Digest": "96be48cccb522690d0b6bb55e427bf366e7160213ef4c953ae240b66d1a5d100",
        "X-Served-By": "cache-fjr7922-FJR",
        "X-Cache": "MISS",
        "X-Cache-Hits": "0"
      },
      "status": 200
    }
  },

  #↑の配列がPOPの数だけこの後に続きます。

ポイントは、このAPIで確認できるのはそのURLにリクエストを投げた時のレスポンスヘッダステータスコードだけで、bodyの内容は確認できないということです。
つまり、前回作ったsyntheticレスポンスによるJSONはこれでは確認できません。

syntheticレスポンスを工夫する

ではどうするか、おそらく一番簡単なのは、JSONにも出力していたreq.backend.healthy をレスポンスヘッダに含める方法です。そうすることで、このAPIのレスポンスヘッダにhealth状態を出力させることができます。

前回の記事を前提にお話すると、vcl_errorのコードに1行だけ付け加えればOKです。vcl_recvのコードは前回のままで問題ありません。

  • vcl_error
if (obj.status == 610) {
  synthetic "{" LF
      {"  "timestamp": ""} now {"","} LF
      {"  "req.backend": ""} req.backend {"","} LF
      {"  "req.backend.healthy": "} req.backend.healthy LF
      "}"
  ;
  set obj.status = 200;
  set obj.response = "OK";

  # ヘッダにbodyへのJSON同様に `req.backend.healthy` を出力する
  set obj.http.X-Backend-Healthy = req.backend.healthy;
  set obj.http.Content-Type = "application/json";
  return (deliver);
}

APIへリクエストを投げる

${hostname}: Fastlyのサービスに登録しているドメイン
${backend_name}: backend名
${your_fastly_token}: API token

$ curl https://api.fastly.com/content/edge_check?url=${hostname}/api/status?backend=${backend_name} -H 'Fastly-Key: ${your_fastly_token}'

これを叩くとJSONがババーっと返ってくると思います。

[
  {
    "hash": "a6fa75cf5b77f61527421aaaa4ddcd50",
    "pop": "fjr-ae",
    "response_time": 0.399193,
    "server": "cache-fjr7922",
    "request": {
      "headers": {
        "User-Agent": "Fastly/cache-check",
        "Fastly-Debug": 1,
        "Host": "<name>.global.ssl.fastly.net"
      },
      "method": null,
      "url": null
    },
    "response": {
      "headers": {
        "Server": "Varnish",
        "Retry-After": "0",
        "Content-Length": "191",
        #↓これ↓
        "X-Backend-Healthy": "1",
        "Content-Type": "application/json",
        "Accept-Ranges": "bytes",
        "Date": "Wed, 21 Feb 2018 07:51:53 GMT",
        "Via": "1.1 varnish",
        "Connection": "close",
        "Fastly-Debug-Path": "(D cache-fjr7922-FJR 1519199513)",
        "Fastly-Debug-TTL": "(M cache-fjr7922-FJR - - -)",
        "Fastly-Debug-Digest": "96be48cccb522690d0b6bb55e427bf366e7160213ef4c953ae240b66d1a5d100",
        "X-Served-By": "cache-fjr7922-FJR",
        "X-Cache": "MISS",
        "X-Cache-Hits": "0"
      },
      "status": 200
    }
  },

  #↑の配列がPOPの数だけこの後に続きます。

出力は上記のようになるはずです。
"X-Backend-Healthy": "1", という部分が今回追加したレスポンスヘッダです。0=unhealthy, 1=healthy です。

これを頑張ってパースしてPOPごとのヘッダに切り分ければ、各POPでのbackendのhealth状態をこのAPIによって取得することができます。