Lambda@Edgeを使って色々と試してみようとした

この記事はWanoグループ Advent Calendar 2016の18日目の記事です。

はじめに

Wanoでは、webサーバーの前にCloudFrontを配置し、全てのリクエストを一旦CloudFrontで受けて極力キャッシュを返す形を取ることが良くあります。
この構成のメリットは、サーバーサイドでキャッシュの仕組みを構築しなくても、CloudFrontを前に配置するだけで、EC2にリクエストを流すことなくパフォーマンスを改善できることにあります。

ただ、この構成には弱点も当然あり、ログイン機能が無いサービスの運用には最適なのですが、ログイン機能があるサービスの場合、ログイン状態によってキャッシュを返すかどうかの判定ができないため、ユーザーの9割がログインせずに使用するサービスでも、この構成が一切使えないといった弱点があります。

そんな中、先日のRe:Inventで発表されたのが、このLambda@Edgeです。
本当はLambda@Edgeを実際に使ってみていろいろ試してみようと思っていたんですが、プレビューへの申込みが遅かったためかまだ実際に動かすことができなかったので、ひとまず現時点で試したこと、わかったことを書いておきたいと思います。

Lambda@Edgeの設定

実際にCloudFrontに設定して動かすことはできなかったのですが、辛うじてLambdaのテスト機能で動かすことはできたので、blueprintのコードをベースに、少しだけ試してみました。
まずは設定画面です。

Lambda@Edgeは、CloudFrontのDistributionに対して設定するので、Distribution IDを指定する画面になっています。
その他にも、BehaviorとEventが指定できました。Behaviorが指定できるということは、LambdaFunctionを動かすURLと動かさないURLを分けることができるということなので、静的コンテンツ用にはBehaviorを分けて、LambdaFunctionを実行させずに、パフォーマンスとコスト面への考慮ができそうです。

Eventですが、以下の4つを指定できました。

今回は、この4つのEventからViewer Requestを指定してLambdaのblueprintの中から、cloudfront-ab-testを選択して設定します。

Viewer Request

ブラウザ等のクライアントからCloudFrontがリクエストを受け付けた時に発火するイベントです。
個々のリクエストに対して何か処理を追加する場面で使用するイベントになるため、4種類のイベントの中で最も使う頻度が多いのではないでしょうか。

cloudfront-ab-testを読んでみて

以下のコードが使い方を端的に表しているんじゃないでしょうか。
まだ動かせていないので、実際の挙動はわからないのですが、CookieやHeaderを見て条件に応じてURLをRewriteする。というパターンは使い勝手がありそうな気がします。

let modifiedUri = false;
if (headers.Cookie) {
    for (let i = 0; i < headers.Cookie.length; i++) {
        const experimentIndex = headers.Cookie[i].indexOf(experimentCookieName);
        console.error(experimentIndex);
        if (experimentIndex >= 0) {
            if (headers.Cookie[i][experimentIndex + experimentCookieName.length] === groupA) {
                request.uri = groupAObject;
                modifiedUri = true;
            } else if (headers.Cookie[i][experimentIndex + experimentCookieName.length] === groupB) {
                request.uri = groupBObject;
                modifiedUri = true;
            }
        }
    }
}

書いていて気づいたんですが、Wanoグループ Advent Calendar 2016の前日の記事nginx で特定のIPのみ別の upstream を使うについてもLambda@Edgeで同じようなことができそうですね。

少し前に発表されて、既にTokyoリージョンでも使用できるようになっているALBと組み合わせると、リクエストの捌き方をこれまで以上に柔軟に構成できそうです。

元々やりたかった、ログイン状態に応じてキャッシュを返すかどうかを切り替える場合も、少なくともRewriteすれば対応できそうなので、弊社でも使えるようになったら実際の挙動とパフォーマンスをしっかりチェックしたいと思います。

Read More