話題の次世代CDN Fastlyを触ってみた〜VCLカスタマイズまで


Fastlyとは

Twitter社やGitHub社も利用している、急成長中のCDNサービスです。
以下記事によると、Fastly社は総額1億3000万ドルも調達している様子。
http://jp.techcrunch.com/2015/08/06/20150805fastly-raises-75m-series-d-round-for-its-real-time-cdn/

Fastlyの特徴として、Varnishを使ってCDNを構築している点が挙げられます。
Varnishを使用することで、キャッシュのリアルタイムパージ(150ms)やVCL(Varnish Configuration Language)を使った柔軟な設定カスタマイズを可能にしています。

Fastlyを使ってみる

アカウント作成、初期設定

以下記事を参照ください。今回、一般的なCDN設定の説明は省きます。
http://dev.classmethod.jp/server-side/fastly1/
特徴的な機能の一つであるキャッシュのリアルタイムパージについても、上記記事で紹介されているので省きます。
以下、いくつか試してみて良いと思った機能について書きます。

設定のバージョン管理

設定変更が全てバージョン管理されており、簡単に設定を切り替えたり、設定の差分を見ることが出来ます!
これで安心して設定を適用できますね。

Versionのプルダウンメニューからバージョン番号を選択し、Activateを押すとバージョンが適用されます。
また、設定情報は全てドキュメント管理されており、バージョン間の差分も確認できます!

VCLカスタマイズ

Varnishを知らない方のために説明しておくと、VCLはVarnish Configuration Languageの略で、C言語に似た文法で記述するVarnish設定用の言語です。これを使ってCDNの挙動を自由にカスタマイズできるというのです。
※VCLカスタマイズは自由度が高くその分危険性も高まるため、デフォルトでは使用出来ないようになっています。サポートに問い合わせたら使えるようにしてくれました。

提供されるboilerplateを元に、VCLをカスタマイズしていきます。Fastly側の設定は#Fastlyとしてマクロ化されています。

VCLのboilerplatは以下です。変更される可能性があるので、正しくは公式サイトを参照ください。
https://docs.fastly.com/guides/vcl/mixing-and-matching-fastly-vcl-with-custom-vcl

boilerplate
sub vcl_recv {
#FASTLY recv

    if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
      return(pass);
    }

    return(lookup);
}

sub vcl_fetch {
#FASTLY fetch

  if ((beresp.status == 500 || beresp.status == 503) && req.restarts < 1 && (req.request == "GET" || req.request == "HEAD")) {
    restart;
  }

  if(req.restarts > 0 ) {
    set beresp.http.Fastly-Restarts = req.restarts;
  }

  if (beresp.http.Set-Cookie) {
    set req.http.Fastly-Cachetype = "SETCOOKIE";
    return (pass);
  }

  if (beresp.http.Cache-Control ~ "private") {
    set req.http.Fastly-Cachetype = "PRIVATE";
    return (pass);
  }

  if (beresp.status == 500 || beresp.status == 503) {
    set req.http.Fastly-Cachetype = "ERROR";
    set beresp.ttl = 1s;
    set beresp.grace = 5s;
    return (deliver);
  }

  if (beresp.http.Expires || beresp.http.Surrogate-Control ~ "max-age" || beresp.http.Cache-Control ~"(s-maxage|max-age)") {
    # keep the ttl here
  } else {
    # apply the default ttl
    set beresp.ttl = 3600s;
  }

  return(deliver);
}

sub vcl_hit {
#FASTLY hit

  if (!obj.cacheable) {
    return(pass);
  }
  return(deliver);
}

sub vcl_miss {
#FASTLY miss
  return(fetch);
}

sub vcl_deliver {
#FASTLY deliver
  return(deliver);
}

sub vcl_error {
#FASTLY error
}

sub vcl_pass {
#FASTLY pass
}

VCLカスタマイズのテストとして、UA判定により飛ばすURLを制御してみます。

custom1.vcl
sub vcl_recv {
#FASTLY recv

    # UAがiPhoneの場合は/test2.htmlへ飛ばす
    if ( req.http.user-agent ~ "(iPhone)+" ){
        set req.url = "/test2.html";
        return(pass);
    }

    if (req.request != "HEAD" && req.request != "GET" && req.request != "FASTLYPURGE") {
      return(pass);
    }

    return(lookup);
}

そして、作成したVCLをアップロードし、Activateすると適用されます。

無事、iPhoneで見た場合にURLを切り替えることが出来ました。

ちなみに、わざとシンタックスが間違っているVCLをアップロードしてみたのですが、ちゃんとエラーが出てActivate出来ないようになりました。

感想

初期設定はとても簡単で、機能も多く、良いCDNだと思いました。今回は触れてないですが、analytics機能もあり、レスポンスタイムやヒット率を確認することが出来ます。
VCLカスタマイズは便利な機能ですが、無闇にいじると事故を起こしそうなので、ある程度Varnishの知識がある人でないと手を出すのは危険です。
オールアバウトではオンプレミスでVarnishを運用しているので、コストや速度次第では移行するのもありかなと思いました。