LoginSignup
2
5

More than 1 year has passed since last update.

FastlyでLoad BalancingしつつオリジンごとにHostヘッダを書き換える

Last updated at Posted at 2017-08-22

現在この方法は必要なくなりました。
下記のように backend 毎に設定できる override host 設定を使うことが推奨されています。


先に結論

directorを使ってset req.backend = autodirector_;のような処理を入れた場合、各サブルーチンからreq.backendの変数を参照することが出来ません。理由としては、最終的にbackendが決定されるのがvcl_missを通りオリジンにリクエストを発行する直前であるため、例えvcl_missの内部であっても変数の値を知ることができません。
これにより、例えばオリジンに2つのS3バケットが設定されており、それぞれのS3バケットにアクセスする際にHostヘッダを書き換えたい場合、実際にset req.backend = autodirector_;によってどちらのbackendが選択されたか知ることが出来ないため、適切なHostヘッダを設定できません。

回避策としてrandombool()を使って類似の振る舞いを実現するのが本記事のゴールです。

FastlyでLoad Balancingを使う

Fastlyで複数オリジンに対してLBさせるには二通りの方法があります。

  • GUIから設定できるAuto load balanceを使う
  • カスタムVCLを使って自分でdirectorを定義する

[参考]
Fastly Load balancing
Load-balancing configuration

GUIからAuto Load Balanceを使う

下記の画像はGUI(Origins->Hosts->CREATE HOST)からAuto load balanceを有効にする際の設定画面です。

  • GUIからAuto load balanceを設定する場合、オプション項目としてWeight(重み付け)のみ設定できます。

スクリーンショット 2017-08-22 22.37.11.png

生成される関連VCLコード

director autodirector_ random {   
   {
    .backend = F_server2;
    .weight  = 100;
   }{
    .backend = F_server1;
    .weight  = 100;
   }
}

sub vcl_recv {
#--FASTLY RECV BEGIN
    # (中略)

    set req.backend = autodirector_;

    # (中略)
}

カスタムVCLを使って自分でdirectorを定義する

  • ↑↑に書いたVCLコードを参考に、カスタムVCLに直接directorの設定を書いてしまえばOKです。
    Tipsとしては、directorの振る舞いとして上記のrandom以外にround-robin, hash, clientの計4種類が利用できますGUIからは変更できません。
  • directorを書いたら、前項の例のように任意の場所で必要な条件を設定してset req.backend = autodirector_;のようにbackendを決定するコードを書いてください。
  • カスタムVCLにdirectorを直接書く場合、GUIからAuto load balanceを有効にする必要はありませんが、利用するオリジンは事前にGUIから設定してください。Show VCLボタンを押して表示されたVCLからbackend名を見つけて正しく設定してください。(前項の例で示すところのF_server1部分)

Load Balancingしつつreq.http.hostを書き換えたい

  • ごく稀なユースケースだとは思いますが、ロードバランスしつつそれぞれのオリジンにアクセスする時にHostヘッダを変更する必要がある場合、一見すると下記のようなコードで動作するように見えますが、期待する動作にはなりません。理由は本記事の先頭に書いた通りです。
director autodirector_ random {   
   {
    .backend = F_server2;
    .weight  = 100;
   }{
    .backend = F_server1;
    .weight  = 100;
   }
}

sub vcl_recv {
#--FASTLY RECV BEGIN
    # (中略)

    set req.backend = autodirector_;

    if (req.backend == F_server1) {
        set req.http.host = "server1.example.com";
    }else if (req.backend == F_server2) {
        set req.http.host = "server2.example.com";
    }

    # (中略)
}

つまり、残念ながらdirectorを使ったロードバランスではこれを実現することができません。

回避策としてのrandombool()

  • FastlyではVCLの中でrandombool()を使うことができます。
    これを代用することでdirectorを使ったロードバランス同様の振る舞いを表現してみます。
sub vcl_recv {
#--FASTLY RECV BEGIN
    # (中略)

    if (randombool(1, 4)) {
        set req.backend = F_server1;
        set req.http.host = "server1.example.com";
    }else{
        set req.backend = F_server2;
        set req.http.host = "server2.example.com";
    }

    # (中略)
}

上記の例では、1/4のリクエストがtrueとなるので、リクエストのうち25%はF_server1、残りはF_server2へ振り分けられることになります。
このようにrandomboolを使うことでdirectorでweightを設定した時と同様の振る舞いが実現できました。
またrandomboolの他にシード値を与えることができるrandombool_seeded()も利用することができます。
randombool_seeded()を応用することでcookieレスなA/Bテストなども実現可能です。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5