Lambda@Edgeを利用した画像のリサイズを試してみた

Pocket

こんにちは。技術開発部部長の川住です。

弊社プロダクトにて、「オリジナル画像を適切な大きさに縮小してから読み込む仕組み」を作る必要が生じたので、遅ればせながらLambda@Edgeを使ってみたので、利用時のポイントを紹介したいと思います。

Lambda@Edgeとは?

Lambda@Edgeは、Amazon CloudFrontのエッジサーバで、AWS Lambdaの関数を実行できる仕組みです。リクエスト-レスポンス間の以下4つのタイミングに対してLambda関数を設定できます。

  • CloudFrontのエッジサーバがユーザからのリクエストを受け取る時 (Viewer Request)
  • (エッジサーバにキャッシュがなく)、オリジンサーバへリクエストを転送する前 (Origin Request)
  • オリジンサーバからレスポンスを受信した後 (Origin Response)
  • エッジサーバからユーザへレスポンスを転送する前 (Viewer Response)

Lambda関数に機能を実装することで、例えば以下のような仕組みを実現できます。

  • ユーザ認証やリダイレクトを行う
  • HTTPヘッダを操作する (追加, 削除, 変更)
  • コンテンツを必要に応じて加工してレスポンスする

Lambda@Edgeを使用した画像のリサイズ

Lambda@Edgeを利用した画像のリサイズの仕組みの構築方法に関しては、こちら にて詳しく紹介されていますので、実装の詳細については割愛します。大雑把に言いますと、2つのLambda関数を実装しそれらをCloudFrontに設定することで実現しています。

  • Viewer Requestとして、リサイズ後の幅や高さなどのパラメータを受け取り、パスに組み込む関数をCloudFrontに登録する
    • エッジにリサイズ後の画像のキャッシュがあれば、オリジンへリクエストは転送されず、キャッシュデータがレスポンスされる
  • Origin Responseとして、必要に応じてオリジンから受け取った画像をリサイズし、レスポンスとして返す関数をCloudFrontに登録する
    • オリジンにリサイズ後の画像がすでに保管されている場合は、保管されている画像をレスポンスする
    • オリジンにリサイズ後の画像が保管されていない場合は、画像を取得してリサイズした後、オリジンにデータを格納し、画像をレスポンスする

Lambda@Edge利用時のポイント

Lambda@EdgeはAWS Lambdaと同様の制約を受けるほかに、Lambda@Edge特有の制約や注意点があったので紹介します。

スペック面での制約

AWS Lambdaでは実行時のメモリ量やタイムアウト時間を設定できますが、Lambda@Edgeでの実行時にはこれらの設定上限が通常よりも厳しくなります。

  • メモリ量の上限: 128MB
  • タイムアウトの上限: 5秒

その他制約に関してはこちらが詳しいです。また、AWS Lambdaでは複数の言語をサポートしていますが、Lambda@Edgeで使用できるのは「 node.js 6.10, node.js 8.10 」のみとなっています。

Lambda関数はus-east-1 (バージニア北部) に登録する必要がある

CloudFrontに設定できるLambda@Edge関数はバージニア北部に登録されているものだけです。

バージョンつきのarnを紐つける必要がある

CloudFrontには $LATEST$ALIAS のarnを設定できないので、バージョンを発行したLambda関数をCloudFrontに設定する必要があります。

実行時のCloudWatch Logはエッジサーバのリージョンに排出される

Lambda関数の登録自体はus-east-1 (バージニア北部) ですが、実行はCloudFrontのエッジサーバであるため、実行時のCloudWatch Logの排出先はエッジサーバのロケーションに依存します。 (日本からアクセスした場合には、東京、ソウル、シンガポールリージョンあたりにログが排出されていました。大半は東京。)

使ってみた感想

  • 今回の用途以外にも、A/Bテストなどにも利用できそう
  • 大量アクセスのある場面には注意が必要
    • リクエスト数とLambdaのコード実行時間に比例して利用料金が発生。キャッシュヒット率を高める工夫が必要になってきそう。

今回は以上となります。