ドキュメントを通してre:Invent 2016キーノートで発表されたLambda@Edgeを理解する #reinvent
はじめに
こんにちは、中山です。
re:Invent 2016に参加中です。現地時間12/1(木)の8:30から実施されたWerner Vogels氏によるキーノートの中で発表された新サービス、Lambda@Edgeについてまとめます。残念ながらまだプレビュー版で利用するには申請が必要です。まずは実際に利用する前にドキュメントを参照してどういったものなのかをまとめたいと思います。今回参照するドキュメントは以下のとおりです。
Lambda@Edgeとは何か
ドキュメントにずばり書かれています。
Lambda@Edge (preview) allows you to run Lambda functions at the AWS Edge locations in response to CloudFront events, without provisioning or managing servers, by using the AWS Lambda serverless programming model.
つまり、CloudFrontのエッジロケーション上でLambda関数を実行可能、かつCloudFrontの各種イベントに基づきイベントドリブンに実行されるよ、しかもサーバーレスなのでサーバのお守りしなくてもいいよということです。至れり尽くせり感すごい。
Lambda@Edge登場以前でもCloudFrontへの特定の情報を契機に(ヘッダの情報など)オリジン側で変更を加えるといったことは可能でした。が、これではオリジンまでトラフィックが届く必要があるためネットワークレイテンシ上の問題がありました。Lambda@Edgeの登場により高速にかつサーバーレスな形でこういった問題点に対して対応可能になったというわけです。
Lambda@Edgeのユースケース
Lambda関数が実行可能なので自分にあった動作に調整可能ですが、主なユースケースとしては以下のようなものがあります。
- A/Bテストを実施するためにクッキーを解析/挿入してクライアント毎に異なるURLを返す
- ユーザエージェントに基いてレスポンスとして返すオブジェクトをクライアント毎に変更する
- 例えば、クライアントのデバイスに最適化された画像を返却する
- ヘッダやトークンを解析して、それらに対応するヘッダを挿入し、オリジンへリクエストが届く前にアクセスコントロールとして利用する
- エッジロケーションでキャッシュされているオブジェクトについて、ヘッダに対し各種操作(追加/削除/変更)を実施し、URLを変更して異なるオブジェクトを返す
CloudFrontのイベントにはどういったものがあるのか
こちらのドキュメントに詳しいです。まとめると現状以下の4つのイベントがあります。
CloudFront Viewer Request
- クライアントからのリクエストがCloudFrontに届く前かつCloudFrontのキャッシュ検索が実施される前
CloudFront Origin Request
- クライアントからのリクエストがCloudFrontからオリジンへ転送される前に発生するイベント
- CloudFrontがリクエストをオリジンに転送する際にのみ発生する
- つまり、オブジェクトのフェッチなどエッジロケーション起源のリクエストに関してこのイベントは発生しない
CloudFront Origin Response
- オリジンからのレスポンスがCloudFrontで受信された後かつCloudFrontによってこのレスポンスがキャッシュされる前に発生するイベント
- このイベントはCloudFrontがリクエストをオリジンに転送する際にのみ発生する
- つまり、オブジェクトのフェッチなどエッジロケーション起源のリクエストに関してこのイベントは発生しない
CloudFront Viewer Response
- CloudFrontからクライアントへレスポンスを返す前に発生するイベント
- レスポンスとして返すコンテンツはエッジロケーションにすでにキャッシュされているオブジェクトでも、キャッシュがなくオリジンからフェッチしたものでも両方共このイベントは発生可能
イベント発生時にLambda@Edgeへはどういった情報が渡されるのか
レスポンスとリクエストで異なるようです。
- リクエストの場合
{ "Records":[ { "cf": { "configuration": { "distributionId": "EXAMPLE" }, "request": { "uri": "/me.pic", "method": "GET", "httpVersion": "2.0", "clientIp": "2001:cdba::3257:9652", "headers": { "User-Agent": ["Test Agent"], "Host" : ["d2fadu0nynjpfn.cloudfront.net"] } } } } ] }
キー | バリュー | 読み書き |
---|---|---|
uri | CloudFrontからリクエストされたコンテンツの相対パス。このバリューを更新することで提供するオブジェクトを変更できる。 | 両方可 |
method | リクエストのHTTPメソッド。 | 読み込みのみ |
httpVersion | リクエストのHTTPバージョン。 | 読み込みのみ |
clientIp | リクエストの送信元IPアドレス。 | 読み込みのみ |
headers | リクエストのヘッダ。ヘッダはリストの中にキーペア形式で表現される。現状全てのヘッダが操作可能というわけではなくいくつか制限がある。 | 両方可 |
- レスポンスの場合
{ "Records":[ { "cf": { "configuration": { "distributionId": "EDFDVBD6EXAMPLE " }, "response": { "status": "200", "statusDescription": "HTTP OK", "httpVersion": "2.0", "headers": { "User-agent": [ "mozilla", "safari" ], "Vary": [ "*" ] } } } } ] }
キー | バリュー | 読み書き |
---|---|---|
status | クライアントへ返すHTTPステータスコード。 | 読み込みのみ |
statusDescription | クライアントへ返すHTTPステータスコード。 | 読み込みのみ |
httpVersion | クライアントへのレスポンスで利用されるHTTPプロトコルバージョン。 | 読み込みのみ |
headers | レスポンス内のHTTPヘッダ。ヘッダはリストの中にキーペア形式で表現される。現状全てのヘッダが操作可能というわけではなくいくつか制限がある。 | 両方可 |
ヘッダの制限はどういったものがあるのか
読み書き両方共不可能な「blacklisted headers」と、読み込みのみ可能な「read-only headers」の2つのタイプがあります。それぞれのヘッダにはどういった種類があるのかについてはこちらのドキュメントを参照してください。ここに記載されていないヘッダについては読み書き可能ということです。
実際のところどんな感じで使えるの?
現地時間の今日プレビューに応募したのでまだ実際には使えてないですが、こちらのドキュメントなどにサンプルコードがまとめられています。また、Lambda関数のブループリントにも複数のサンプルコードが上がっている模様です。次回以降で使ってみた内容をレポートしたいと思います。
まとめ
いかがだったでしょうか。
まだプレビュー段階ですが個人的にはかなり期待できる機能だと思いました。もう少し使い込んでからより詳細なレポートにまとめたいと思います。
本エントリがみなさんの参考になれば幸いです。