この記事はRetty Advent Calendar 2024の11日目の記事です️。
Rettyプラットフォームチームの今村です。 RettyではContent Delivery Network(CDN)にFastlyを利用しています。今回はFastlyで複数のバックエンドを利用している環境にオリジンシールドを設定する方法についてご紹介します。
オリジンシールドとは
Fastlyにはオリジンシールドという機能があります。 オリジンシールドを有効化するとFastlyのPOP(キャッシュの配信サーバ)とオリジンサーバの間にシールドPOPと呼ばれるPOPを配置します。
FastlyではそれぞれのPOPは独立していて特定のPOPにアクセスした場合、キャッシュが存在しなければオリジンサーバを参照します。 そのためオリジンサーバへのリクエストが多くなり負荷増加になる場合があります。
オリジンシールドを有効化するとオリジンサーバの前にシールドPOPが配置されます。 特定のPOPにキャッシュが存在しない場合、シールドPOPを参照してキャッシュが存在すれば応答、存在しなければオリジンサーバを参照します。 そのためどのPOPへアクセスしてもシールドPOPにキャッシュが作成されるのでキャッシュヒット率の向上やオリジンサーバへのリクエスト削減が見込めます。
Fastlyで設定しているオリジンサーバが1つであればFastlyのドキュメントに記載されている手順で対応可能ですが、オリジンサーバを複数設定している場合はこちらの設定だけではオリジンシールドを有効化できません。
オリジンサーバを複数設定している環境でオリジンシールドを設定してみる
では実際にオリジンシールドを設定してみます。 なお本手順ではVCLを利用しています。
1. どのPOPをシールドPOPとして使用するかを設定
Fastly コントロールパネルでHostsのShielding
欄に設定を追加します。
今回はtyo-tokyo-jp
をシールドPOPとして設定しました。
シールドPOPに設定できるPOPはAPIで取得できます。
日本ではosaka-jp
, nrt-tokyo-jp
, tyo-tokyo-jp
から選択できます。
2. カスタムVCLのvcl_recvにオリジンを決定するための変数を定義
カスタムVCLのvcl_recv
サブルーチンにバックエンドを決定するための変数を定義します。
例えば下記のように記載します。
sub vcl_recv { declare local var.backend_retty_1 BOOL; declare local var.backend_retty_2 BOOL; }
3. Fastly コントロールパネルで各バックエンドに条件を作成
Fastlyコントロールパネルにて、Conditionsから新しく条件を追加して各バックエンドに紐づけます。
Apply if...
に先ほど作成したバックエンド決定用変数の値がtrueの場合として記載します。
作成した条件を各バックエンドに紐づけます。 Fastly コントロールパネルにて、Hostsから各バックエンドに作成したConditionsを紐づけます。
https://docs.fastly.com/ja/guides/using-conditions
4. カスタムVCLのvcl_recvにバックエンドを決定するためのコードを追加する
カスタムVCLのvcl_recv
サブルーチンにオリジンサーバを決定するためのロジックを記載します。
例えばリクエスト先のパスが^/backend1
とそれ以外とでオリジンサーバをわける場合、下記のようにします。
sub vcl_recv { declare local var.backend_retty_1 BOOL; declare local var.backend_retty_2 BOOL; if (req.url ~ "^/backend1") { set var.backend_retty_1 = true; } else { set var.backend_retty_2 = true; } #FASTLY recv }
なお、#FASTLY recv
はマクロになっていて、Fastly コントロールパネルで作成したConditionsのコードなどが生成されるため、今回のロジックは#FASTLY recv
のマクロより前に記載する必要があります。
マクロ部分がどのようなコードになるかは、カスタムVCLをアップロード後にFastly コントロールパネルで対象サービスのShow VCL
から確認できます。
オリジンシールドの設定は以上となりますが、デバッグ方法などドキュメントに記載されているため参照してみてください。
効果
オリジンシールドを有効化後、バックエンドに設定しているオリジンサーバの台数が約半分ほどまで減少しました。
注意点
料金について
オリジンサーバへのリクエスト数が減ることで通信量などを節約できますが、エッジPOP*1からシールドPOPへのデータ転送料金が追加で請求されます。 そのため、オリジンシールドを設定してもFastly + オリジン合計の料金が下がらないといった場合もあるため注意が必要です。
シールド POP へのインバウンドトラフィックは、エッジ POP への配信分を含め、通常のトラフィックとして請求対象となります。オリジンシールドを有効にすると、Fastly のデータ転送量料金が追加で発生しますが、オリジンのデータ転送量 (およびオリジンサーバーの負荷) を節約することで、これらの料金が相殺される可能性があります。PASS (キャッシュ対象外) となるリクエストも直接オリジンには送られず、最初にシールド POP を経由することにもご留意ください。
HTTPヘッダについて
またエッジPOPとシールドPOPで2回VCLが実行されるため、カスタムVCLを利用してHTTPリクエストやHTTPレスポンスの内容を書き換えていると期待したレスポンスが得られない場合もあります。 例えばカスタムVCLでHostヘッダを書き換えていると500エラーが発生することもあります。Fastlyのドキュメントにも記載されていますが、Fastlyでオリジンに設定しているドメイン名とHostヘッダの名前が一致しないためです。
シールドにリクエストが到達する前の Host ヘッダーの変更には注意が必要です。Fastly はリクエストと Host ヘッダーを照合します。Host ヘッダーがサービス内のドメインに一致しない場合、500 エラーが予想されます。
このような場合は下記のようにHostヘッダ書き換え時にreq.backend.is_origin
変数でバックエンドがオリジンかどうかを判定して、オリジンの場合のみ書き換えることで対処できます。
if (req.backend.is_origin) { set bereq.http.host = "<host name>"; }
req.backend.is_origin
変数についてはFastlyのドキュメントを確認してください。
バックエンドがシールドPOPかどうかを判定するreq.backend.is_shield
変数なども用意されています。
そのほかの注意点もFastlyのドキュメントに記載されています。
まとめ
Fastlyで複数のバックエンドを利用している環境でオリジンシールドを設定する方法について紹介しました。 オリジンシールドを有効化して効率的にキャッシュすることでオリジンへのリクエスト量を節約でき、オリジンサーバの台数削減に繋がりました。 Fastlyを利用している方やこれから使おうと思っている方の参考になれば幸いです。
また、オリジンシールドの設定にあたりFastlyサポートに丁寧に疑問点を解消してもらいました。サポートチームの皆さんありがとうございます。
参考URL
https://www.fastly.com/documentation/guides/concepts/shielding/ https://docs.fastly.com/ja/guides/shielding https://www.fastly.com/documentation/reference/vcl/variables/backend-connection/req-backend-is-origin/ https://www.fastly.com/documentation/reference/api/utils/pops/
*1:シールドPOP以外のPOPをエッジPOPと記載しています。