AWS LambdaとAPI Gatewayを触ってみたのでメモ
PyCon JP スプリントの時に id:iktakahiro さんがLambdaの話をしていたのですが、Lambda + API Gatewayは覚えとくと便利そうなので試してみた。
Lambdaを触ってみる
まずAPI Gatewayは考えずに、Lambdaを触ってみる。 調べてみたら、公式のドキュメントにも今やりたいことに似たものがあった。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-example.html
事前に、下のことをしておいた。
- Lambda実行用のIAMロールを作成
- RoleType: AWS Lambda
- Policy: AWSLambdaFullAccess, AmazonS3FullAccess, AWSLambdaBasicExecutionRole
- S3のバケットを2つ用意。
- bucketとlambdaは同じリージョンに作る
hoge-image-source
: 直接アップロードされた画像hoge-image-resized
: Lambdaによってサイズを変更した画像
image-resized
にtest.jpg
という画像データを保存- Lambdaの動きを確認する時に、
test.jpg
がcreatedされたというサンプルイベントデータを渡す。
- Lambdaの動きを確認する時に、
デプロイパッケージを作成
Pillowみたいなサードパーティのライブラリを使うときは、それらを一緒にzipに固めたデプロイパッケージを作る。
デプロイパッケージに含めるものは、 id:iktakahiro さんいわく ./vendors
に入れておくのがいいらしいのでとりあえず真似してみる。
$ virtualenv -p python2.7 venv # Python3使えないので注意 $ source venv/bin/activate $ pip install pillow -t ./vendors $ ls vendors/ PIL Pillow-3.3.1.dist-info
ただ、この方法はPillowとか使う場合うまくいかなかった。
Unable to import module 'lambda_function': /var/task/PIL/_imaging.so: invalid ELF header
ではまった。どうやらMacでビルドするのが行けないらしい。 Amazon LinuxのインスタンスをEC2で立ち上げてビルドした。 Dockerでうまくビルド出来るようにすると楽になれそう。
@c_bata_ あー Pillow は駄目だねぇ。軽く使いたいだけならこういうのもあるけどね https://t.co/tMtbYU6oxB
— Takahiro Ikeuchi (@iktakahiro) October 2, 2016
こういうビルド済みのファイルを提供しているリポジトリもあるらしい。
コードを書く
thumbnail-generator.py
from __future__ import print_function import boto3 import os import sys import uuid from PIL import Image s3_client = boto3.client('s3') RESIZED_BUCKET_NAME = 'hoge-image-resized' RESIZED_IMAGE_SIZE = (200, 100) def resize_image(image_path, resized_path): with Image.open(image_path) as image: image.thumbnail(RESIZED_IMAGE_SIZE) image.save(resized_path) def lambda_handler(event, context): for record in event['Records']: bucket = record['s3']['bucket']['name'] key = record['s3']['object']['key'] download_path = '/tmp/{}{}'.format(uuid.uuid4(), key) upload_path = '/tmp/resized-{}'.format(key) s3_client.download_file(bucket, key, download_path) resize_image(download_path, upload_path) s3_client.upload_file(upload_path, RESIZED_BUCKET_NAME, key)
アップロード
10MB以上なら、S3を経由してUploadする必要がある。 10MB以下なら、Lambdaの設定画面からUpload出来る。
ログ
こんな感じでグラフ化されている。 それぞれの詳細のログも見れるので、確認したい項目はprintしておけばいいみたい。
動作確認
AWS CLIを使う方法とかもあるけど、ブラウザ上のTestボタンを押す方法が一番手軽な感じ。 CIの導入とかuploadからtestまで一発でやりたくなったら、AWS CLIを使う方法を試して追記。
Testボタン
事前に test.jpg
をアップロード済みなので、ブラウザからS3のPutイベントを発生させてみる。
管理画面でTestって名前がついた青いボタンがあるのでそれを押す。
awsRegionとbucketのarn, name, objectのkeyを変えて実行。
- awsRegion: ap-northeast-1
- s3 > object > key:
test.jpg
- s3 > bucket >
arn: arn:aws:s3:::hoge-image-source
- s3 > bucket >
name: hoge-image-source
ログを見ながらデバッグ。
うまくいくと、 hoge-image-resized
の方にサムネイルが生成されている。
Github
成果物
API Gateway
API Gatewayで画像のアップロード用APIを作りたい。 POSTで画像を受け取って、S3へアップロード、URLを返す。
リクエストの形式
まずリクエストのヘッダやボディがAPI Gateway経由でどのように渡されるのか確認する。 あとで気づいたのだけれど、API Gateway AWS ProxyのSample event templateを見ればわかった。
{ "body": "{\"test\":\"body\"}", "resource": "/{proxy+}", "requestContext": { "resourceId": "123456", "apiId": "1234567890", "resourcePath": "/{proxy+}", "httpMethod": "POST", "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", "accountId": "123456789012", "identity": { "apiKey": null, : (中略) }, "stage": "prod" }, "queryStringParameters": { "foo": "bar" }, "headers": { "Accept-Encoding": "gzip, deflate, sdch", : (中略) }, "pathParameters": { "proxy": "path/to/resource" }, "httpMethod": "POST", "stageVariables": { "baz": "qux" }, "path": "/path/to/resource" }
うん、とても分かりやすい。 楽をさせるために、request bodyはunicodeで渡されるらしい。
2016/10/04 削除
ここに色々書いてたのですが、文字列についてだいぶ大きな勘違いをしてました。 unicode形式だと画像とかファイルは受け取れないと思ってたんですが、普通にencodeすればいいだけなんですね。
レスポンスの形式
知らずにはまったんだけど、レスポンスは次の形式で返す必要がある。
よくよく考えたら、Hello World
みたいに文字列返すだけだとステータスコードとヘッダ渡す場所がないので当たり前だった。
from __future__ import print_function def lambda_handler(event, context): return { "statusCode": 200, "headers": {"headerName": "headerValue", "Foo": "bar"}, "body": "This is body" }
所感・メモ
Lambda
- Pythonは2系のみ
- 300秒まで使える
- バッチ処理とかだと厳しい場合が結構ありそう
- EC2立ち上げる人もいるらしい
- Lambda Functionはバージョニング可能
- VPC対応あり
- CloudWatch EventsのScheduleで定期実行できる
- 勝手にスケールしてくれる
API Gateway
リクエストの情報をかなりラップして渡してくれていて、手軽。
- リクエストのpayloadサイズに10MBの上限がある。画像とかファイルアップロードするときは厳しい
- 結構分かりやすい形式でLambdaにリクエストの情報を送ってくれる
- レスポンスの形式も明確
References
- AWS Lambda で本番/検証環境を切り替える - Librabuch
- Python で パッケージを vendoring しつつ AWS Lambda へデプロイ - Librabuch
- Amazon S3 プロキシとして API を作成する - Amazon API Gateway
- ステップ 2.3: Lambda 関数を作成し、手動でテストする - AWS Lambda
- Amazon API Gatewayが非常に便利なHTTPプロキシとして進化したらしいので使ってみた - Qiita
Amazon Web Services クラウドネイティブ・アプリケーション開発技法 一番大切な知識と技術が身につく (Informatics&IDEA)
- 作者: NRIネットコム株式会社,佐々木拓郎,佐藤瞬,石川修,高柳怜士,佐藤雄也,岸本勇貴
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2016/04/20
- メディア: 単行本
- この商品を含むブログ (1件) を見る