Change the reverse proxy upstream of Nginx by time zone

諸事情 により、VPSでNginxで運用しているリバースプロキシで、下記のように、時間帯によって振り分け先を変更させるようにしてみました。 1

時間の判定には HttpLuaModuleset_by_lua を使いました。nginx-extrasパッケージのインストールが必要です。

$ sudo apt-get install nginx-extras

ここ を参考にNginxに下記の設定を行いました。

(snip)

upstream app-a.example.org {
    server app-a.example.net;
}

server {
    server_name app-a.example.org;
    access_log /var/log/nginx/app-a.access.log;
    location / {
        proxy_pass http://app-a.example.org/;
    }
}

upstream app-b.example.org {
    server app-b.example.net;
}

server {
    server_name app-b.example.org;
    access_log /var/log/nginx/app-b.access.log;
    location / {
        proxy_pass http://app-b.example.org/;
    }
}

server {
    server_name app.example.org;
    access_log /var/log/nginx/app.access.log;
    set $access_a_zone 0;
    set_by_lua $access_a_zone '
        local time = os.date("*t")
        if 0 <= time.hour and time.hour < 12 then
             return 1
        end
    ';

    if ($access_a_zone = 1) {
        rewrite ^ $scheme://app-a.example.org$request_uri permanent;
    }
    rewrite ^ $scheme://app-b.example.org$request_uri permanent;
}

http://app.example.org でアクセスすると、0-11時台は http://app-a.example.net にリダイレクトし、12-23時台は http://app-b.example.net にリダイレクトするだけの設定です。変数access_a_zoneは当初リンク先同様、下記のようにbooleanにしようとしましたが、Ubuntu TrustyのNginx 1.4.6だと期待通りに判定されず、最後のrewriteが実行されてしまうので、0, 1を設定することにしました。

set_by_lua $access_a_zone '
    local time = os.date("*t")
    local access_a_zone = false
    if 0 <= time.hour and time.hour < 12 then
        access_a_zone = true
    end
    return access_a_zone
';

if ($access_a_zone) {
(snip)

カスタムドメインを使う場合、上記の app-a.example.orgapp-b.example.orgCNAME レコードか ALIAS レコードを設定する必要がありますが、今回はリバースプロキシの IPアドレスを app.example.org, app-a.example.org, app-b.example.org それぞれ A レコードとして設定しました。少なくとも現時点ではこの方法でもアクセスできます。

まとめ

リダイレクトしてしまうので、ドメイン名も午前と午後で変わるので、ドメインも変わらないようにするなら app.example.org をリダイレクトし、カスタムドメインをAPIで定時で削除&追加でするとできます。一瞬アクセスできない時間ができてしまいますが。

今のところ解析結果をMemcachedに入れているだけで、特にデータ更新も行わないお遊びのサイトなので今回の方法を取りました。 無料の範囲内で遊ぶために2つもリソース使って、本末転倒じゃないかという内容なので、いろいろお察し下さい…。

footnote

1

制約超えると通知されるメールが増えてきたので…。