※ この記事はエキサイトAdvent Calendar 2018 4日目の記事です。
エキサイトニュースを今年10月にリニューアルしました。エンドユーザーからのリクエスト受け口がfastlyを仲介するシステムにしました。
その時の行なった内容を一部紹介します。
fastly主な特徴
- https://www.fastly.com/
- fastly社が提供するCDN
- ベースがVarnish
- パージを150msecで行う事が可能
- 十分なPOP
- VCLで設定管理
- ほとんどプログラマブルで管理できる
- 多彩なAPI
- ほとんどプログラマブルで管理できる 2
- slackで開発者とコミュニケーションが取れるなどサポートが充実
サイト登録
初回画面にオリジンに使いたいhostとIPを登録するだけです。
オリジンとTLSで通信したい場合は、証明書ホスト名と公開鍵を登録するだけ。これだけでfastlyを導入したサービスが出来上がります。
エキサイトではfastlyをreverse proxyとしても利用して入るため、複数のサービスを登録し、パスによってオリジン向き先を切り替えています。
fastly API
かなり豊富なAPIエンドポイントが用意されていて、後に説明するパージやVCL変更もAPI経由で行えるので、エキサイトニュースではもちろん多用しています。
API経由だけでfastlyの設定変更からデプロイ、運用監視も行えます。「プログラマブルで管理できる」とはAPIの充実さがとても大きいとも感じでいます。
####以下便利メモ
パージAPIについて
https://qiita.com/Satoshi-Ishii/items/319814068eb2fae86cbf
https://docs.fastly.com/api/purge
パージだけでも豊富なエンドポイント用意していて、システム管理手法が色々膨らみます。
APIトークン作成について
https://docs.fastly.com/api/auth#tokens
APIライブラリについて。個人が作ったサードパーティライブラリもあるみたいです。
https://docs.fastly.com/api/clients
Postmanを使ったAPI使用
https://github.com/philippschulte/fastly-postman
上記をPostmanにインポートするだけで使えます。
VCL関連のAPI
https://docs.fastly.com/api/config#vcl
custom VCLをfastlyにアップする
POST /service/{service_id}/version/{version}/vcl
Fastly-Key: FASTLYのAPIトークン
Content-Type: application/x-www-form-urlencoded
Accept: application/json
// POST Param
// ・ nameに新しくアップロードしたいvcl名
// ・ mainはメインにするかのフラグ
// ・ contentはvclの中身
body内容のcontentは、リクエストヘッダのcontent-typeをx-www-form-urlencodedにしてapiリクエストをすれば、
content内容をエスケープしなくてもそのま上げられます。
VCL
fastlyの設定を管理する、Varnish製のプログラム言語
以下のサブルーチンからVCLが成り立っていて、キャッシュ設定やその他CDN・reverse proxy設定を各メソッドに明記しています。
vcl_recv
リクエストの最初で呼ばれ、どのようにリクエストしてゆくか定義する場所
vcl_pass
キャッシュしない時にオリジンのバックエンドにリクエストする前の時に呼び出されます。
vcl_hash
キャッシュの存在確認の時に呼び出されます。
vcl_hit
キャッシュがヒットした時に呼ばれます。
vcl_miss
キャッシュが見つからなかった時に呼ばれます。
vcl_fetch
オリジンからコンテンツが取得できた時に呼ばれます。
vcl_deliver
レスポンスをクライアント側に返す時に呼ばれます
vcl_error
エラーが発生した時に呼ばれます。
以下でわかりやすく説明していて参考にさせてもらいました。
https://reboot.makeall.net/2013/02/14/what-vcl-on-varnish-02/
https://qiita.com/koudaiii/items/6a0efa024842cd48e2fb#varnish%E3%81%AE%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E5%87%A6%E7%90%86%E3%83%95%E3%83%AD%E3%83%BC
fastly社福田さんの記事
https://qiita.com/AtsushiFukuda/items/db26ce0f75998e7e4385
VCLで使える変数や記述方法・正規表現について
https://reboot.makeall.net/2013/02/15/what-vcl-on-varnish-03/
https://reboot.makeall.net/2013/02/18/what-vcl-on-varnish-04/
https://docs.fastly.com/ja/guides/vcl-tutorials/vcl-regular-expression-cheat-sheet
custom VCL
エキサイトニュースでは、コンテンツの出し分け設定・ヘッダ情報作成・cookie作成・キャッシュ設定などを書いています。
また、VCLをgithub管理し、自動でfastlyにアップデートさせるシステムを作り管理しています。
これもapiの柔軟さにかなり助けられました
fiddle
fastly導入当初はVCL修正時、
- VCLを修正
- CUSTOM VCLをfastlyにアップ
- Versionをactiveに設定
- 確認(ダメなら1から・・)
という順序で確認していたのですが、、なんとも確認フローがちょいとめんどい・・
fiddleを使えばちょっとした修正の挙動確認ができ、fiddleで確認してから、自前のCUSTOM VCLに落とす、というフローができました。すごく便利!
Varyヘッダとコンテンツ出し分け
https://www.fastly.com/blog/best-practices-using-vary-header
Varyヘッダによって、パスとURL以外にもキー材料を設けられます。
ざっくりに言うとVary : User_Agent
とヘッダに設けるとUser_Agent毎にキャッシュキーが判定されキャッシュコンテンツ分けられますが、
デバイス毎にキャッシュ内容を分けられる反面、キャッシュヒット率が著しく低下するため、設定には考慮が必要です。などの事が書かれています。
キャッシュキーのデフォルトについて
fastlyでは
- リクエストパスとパラーメタ(
/news/society?_page=2
)+ - ホスト(
www.excite.co.jp
)+ - 謎パラメータ(
#####GENERATION#####
)
という形になっていました。(/news/society?_page=2/www.excite.co.jp#####GENERATION#####
)
パージ
管理画面GUIからワンタッチでパージが行えます。
Surrogate-Key
https://docs.fastly.com/guides/purging/getting-started-with-surrogate-keys
- URLに独自のキーを設定できます。例えば、タグのような感じでユーザー情報、ニュース情報、画像情報のようなカテゴライズさせた情報をページにkeyを貼り、特定のkeyのキャッシュのみを削除したりするのに便利です。
- Surrogate-Keyを設定させる方法は、fastly上のGUIから設定するか、アプリケーション側でレスポンスヘッダーに設定するよう対応します。
エキサイトニュースはコンテンツが自社記事・外部配信からのニュースと更新性が高いため、更新があった記事だけをリアルタイムでパースをかけるシステムを設けています。
また、記事リスト面や「jsでパースさせる枠だけ」といった部分コンテンツにもパースをかけており、更新性を担保しつつ、キャッシュさせているページは無駄にしないようにしています。
DNS
fastlyにオリジンを登録したら
https://<name>.global.ssl.fastly.net/
というURLが発行されるので、こちらでCDNで配信されたコンテンツの確認を行なえます。
エキサイトニュースではfastlyを本番環境に切り変え時、ssl証明書をfastlyに登録した後、[name].map.fastly.net
のマップがfastly側から発行されたので、そちらにCNAME設定をしました。
こちらにも詳しく説明されています。
https://qiita.com/AtsushiFukuda/items/f8efe8a1613a7fda9894
ABテスト
CDNでもABテストは行えます。VCLに簡単に書けるのですごく便利です。
https://www.fastly.com/blog/ab-testing-edge
上記記事がとても参考になります。
一部抜粋しますと
# RECV
if (!req.http.Cookie:ABViewMode) {
# AB判定のクッキーが設定されていない場合
# view_aが10%の確率でヘッダにセットされます
if (randombool(10,100)) {
set req.http.X-ABViewMode = "view_a";
} else {
set req.http.X-ABViewMode = "view_b";
}
} else {
# クッキーが設定されているときは、クッキーのAB判定をヘッダにセット
set req.http.X-ABViewMode = req.http.Cookie:ABViewMode;
}
# FETCH
varyヘッダにAB設定のヘッダを付与させ、コンテンツ出し分けに使う
if (beresp.http.Vary) {
set beresp.http.Vary = beresp.http.Vary ", X-ABViewMode";
} else {
set beresp.http.Vary = "X-ABViewMode";
}
#DELIVER
if (!req.http.Cookie:ABViewMode){
# クッキーにAB設定がなければ、ヘッダのAB設定をセットする
add resp.http.Set-Cookie = "ABViewMode=" req.http.X-ABViewMode ";";
}
のような形でABテストを設定できます。
オリジンのx-forwarded-for、remote_addrの設定など
https://api.fastly.com/public-ip-list
fastlyでは各リージョンのip範囲をapiで公開しています。
例えばオリジン側のnginxでクライアントIPをログなどに出力したい場合、
# qiita投稿時のfastly公開ipリスト
set_real_ip_from 23.235.32.0/20;
set_real_ip_from 43.249.72.0/22;
set_real_ip_from 103.244.50.0/24;
set_real_ip_from 103.245.222.0/23;
...
real_ip_header X-Forwarded-For;
real_ip_recursive on;
上記のようにremote_addrを変更すれば、無事クライアントIPを取得することができます。
apiでipリストが公開されて入るので、システムで管理して動的にACLを管理などもできますね。
最後に
fastlyはとても導入しやすく、
メンテ・運用がプログラマブルで管理しやすく、
チーム開発にも属人的になりにくい体制で運用出来るのが嬉しいなと思いました。
エキサイトニュースはまだまだfastly初心者、キャッシュヒット率をもっとあげられるとか、fastlyでできる事はもっともっとあるので、チューニングを今後もしてゆきたいと思います。
何よりもキャッシュによる速度改善が大きな恩恵です。
ユーザーに喜んでもらえるコンテンツにしてゆきたいですね!