Amazon CloudFront Functionsを使ってお手軽ルーティング

f:id:ecb_hmogaki:20210623213851p:plain

こんにちは、モガキです。
日々、クラウドや機械学習など新しいことを勉強し仕事に活用しております。


2021年5月に出たCloudFrontの最新機能、CloudFront Functionsを早速使ってみたので紹介いたします。
料金や使い方のほか、使う上での注意点にも触れますので是非ご覧ください。

実現したかったこと

只今、当社ではとあるWEBアプリケーションを開発中で、その中でCloudFrontを通してマルチオリジンからコンテンツを配信する要件があります。
あ、オリジンがAzureなのは気にしないでください。

f:id:ecb_hmogaki:20210623155410p:plain

f:id:ecb_hmogaki:20210623162712p:plain

いかがでしょうか。一見普通のマルチオリジンに見えますが、実は静的ファイルのほうはCloudFrontの基本機能だけでは実現できません。
基本機能では要求パスに階層を足すことはできますが、逆の階層を消すことができないのです。

f:id:ecb_hmogaki:20210623162715p:plain


なんとかできないものかと調べているうちに、CloudFront Functionsで実現できそうだということがわかりました。

CloudFront Functionsの機能

CloudFront Functionsは、ビューアリクエスト直後またはビューアレスポンス直前に任意の関数を実行し、オリジンへのリクエスト内容や、ビューアへのレスポンス内容を変更することができる機能です。
なお、Lambda@Edgeという似たような機能が以前からあります。
以下の比較表の通り、CloudFront Functionsは、Lambda@Edgeの機能を絞って高速化、低料金化したものと言ってもよいかもしれません。

f:id:ecb_hmogaki:20210623155413p:plain
AWS公式ブログより引用

具体的なユースケースは、クラスメソッドさんの記事が非常にわかりやすいです。
dev.classmethod.jp

実現方法

それでは具体的な設定方法を説明いたします。

Functionを作成する

CloudFront Functionsの画面からFunctionを作成し、eventオブジェクトのrequest.uriに格納されている要求パスを操作する処理を記述します。
"files/"の6文字を固定で消したいため、request.uri.substring(6)としました。

f:id:ecb_hmogaki:20210623155416p:plain

DistributionにFunctionをバインドする

Cache Behaviorsの画面から、Viewer Requestイベントに先ほど作成したFunctionをバインドします。

f:id:ecb_hmogaki:20210623155419p:plain

これで設定完了です。

CloudFrontFunctionsはLambda@Edgeの6分の1の料金で使える

CloudFront FunctionsとLambda@Edgeの料金を比較してみました。
どちらも非常に安いですが、Lambda@Edgeは実行時間・メモリ使用量にも料金がかかります。

f:id:ecb_hmogaki:20210623202706p:plain

aws.amazon.com

実際の金額を比較するため、CloudFront Functionsと同じ内容をLambda@Edgeで実装して、実行時間・メモリ使用量を計測してみました。

f:id:ecb_hmogaki:20210623155421p:plain

テスト実行してみたところ、メモリ使用量は66MB、実行時間は約1msとなりました。

f:id:ecb_hmogaki:20210623155424p:plain

この結果をもとに、10,000,000リクエスト件数あたりの料金を比較してみました。
パスを書き換える程度であればコンピューティング料金は誤差の範囲となり、単純にリクエスト料金の比較となりました。
CloudFrontFunctionsはLambda@Edgeの6分の1の料金で使える!ということになります。

f:id:ecb_hmogaki:20210623202437p:plain

CloudFront Functionsで気を付けたいこと

安くて素晴らしいのですが、気を付けたいことがいくつかあります。

実行時間が1ms超えると503エラーになる

実行時間は最大1msの制限があり、これを超えると503エラーになってしまいます。
認証系の機能を実装するときは、ブラックリストをループしたり、長い文字列を復号化するなどの実装が考えられますので気をつけましょう。

f:id:ecb_hmogaki:20210623155429p:plain

言語はES5のみ

ES6でサポートされるletやconst等のワードを使えません。
また、Node.jsで書いたLambda@Edgeの機能をそのままコピペで移植できないケースがあります。
Lambda@Edgeから移植する際は不具合を起こさないように気をつけましょう。

オリジンからエラーが返るとViewerResponseが実行されない

オリジンから404などのエラーが返ってくると、ViewerResponseイベントが実行されないようです。
ViewerResponseで必ずヘッダやCookieを編集したいといったときに不都合が出る場合があるので注意しましょう。

終わりに

リクエストの度にFunctionが実行されるとなるとコスト面が心配でしたが、1千万リクエストでも1USDと破格の値段で安心しました。
URLパラメータの正規化など、いろいろなケースで使えるため、今後もケースバイケースでCloudFront Functionsを活用したいですね。

なお当社で開発中の、とあるWEBアプリケーションが商用稼働できるのはもう少し先になりますが、稼働し始めたら紹介したいと思います。

余談ですが個人的にAWS アソシエイトソリューションアーキテクトを取りたいと思っており、少しずつ勉強中です。
無事資格習得できたら、またブログで報告できればと思います😄

お知らせ

ecbeingではサービスの成長のため一緒に試行錯誤してくれる仲間を募集しています!

careers.ecbeing.tech