awsでapi...

45
AWS Lambdaで ハマった話。

Upload: takehiro-suemitsu

Post on 16-Apr-2017

3.195 views

Category:

Engineering


2 download

TRANSCRIPT

Page 1: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

AWS Lambdaで ハマった話。

Page 2: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

最近• AWSをちょいちょいいじる

• AWS Lambdaとやらに⼿を出す

• 盛⼤にハマる

• ある程度知⾒がたまった

• いいタイミングでLTの機会が

Page 3: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

Lambda?

• ランバダ?

• ラムダと読みます

• 以下Lambda

Page 4: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

Lambdaとは• コードをAWSクラウド上で実⾏してくれる

• 対応⾔語はNodeJS,Java,Phython

• AWSクラウド上の⾊々な所で実⾏トリガーを設定できる

• 例えばS3へのファイルアップロード

• DynamoDBのテーブル更新時(insert, update, …)

Page 5: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

例えば• S3に画像がアップロードされた瞬間、サムネイル

画像を⽣成する

• S3にログファイルがアップされたら、即座にファイルの解析を⾏う

• DynamoDBにレコードがインサートされたら、何かをする(利⽤シーン思いつかず)

Page 6: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

デメリット

• 300秒以上かかる処理はできない

• メモリ1.5G以上使う処理はつらい

• Javaが遅い(らしい)

Page 7: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

メリット• EC2いらない

• 安い

• スケーラブル

• 関数に対して割り当てるメモリを調節できる(128M ~1536M)

• CPUはメモリ⽐例して勝⼿に強くなる

Page 8: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

そして

• 最近オンデマンド(https経由)からもLambdaを起動できるようになった!

• これは便利!

Page 9: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

何ができるのか• クライアント(ブラウザ)が直接Lambdaを起動で

きる

• Lambdaに対してGET, POST等でデータを送信できる

• そしてそのデータに応じて/対して⾊々とごにょごにょできる

Page 10: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

ただし

• HTTPS経由でのLambda関数の起動はAWS Lambda単体では実現できない

• ので…

Page 11: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

AWS API Gateway

と、連携します

Page 12: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

API Gatewayとは

• LambdaをHTTPSで呼び出せるようにするやつ

• これに関して詳細解説はしません

• 詳細は公式へどうぞ

• これとLambdaをうまく組み合わせて準備完了

Page 13: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

で、何をしたいのか• ブラウザからポストしたデータをS3に書き出した

• けど書き出してる時間は待ちたくない

• 要はポストするだけして即座に”200 OK”が欲しい

• 厳密に⾔うと202

Page 14: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

理想のイメージクライアント API Gateway Lambda

とりあえず202

⾮同期POST

S3

Page 15: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

まずは普通に やってみる。

Page 16: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

• Node.jsのコードを記述します

• exports.handler = function() {}に渡されいるeventにPOSTされたpayloadが⼊ってます

• 普通にaws-sdkを使ってS3にアップロードしてるだけです

Page 17: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

これを押すと関数のテストが出来ます

Page 18: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

エンドポイントから叩いてみる

ここから⾮同期化を⽬指す。

成功

Page 19: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

⾮同期化への道。

Page 20: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

⾮同期化へのアプローチ

1. 無思考的にsetTimeoutを試す

2. Node.jsのchild_processを使う

3. API Gatewayの統合リクエストヘッダーに X-Amz-Invocation-Typeを追加する

4. LambdaからLambdaを呼び出す

Page 21: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

setTimeout();• S3へのアップロード部分の

実⾏を遅延させてみる

• setTimeout()は実⾏キューへの登録が遅延されるだけで結局同⼀スレッドで実⾏されるので意味なし

• (おさらい)Javascriptはシングルスレッド

Page 22: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

ちなみに• setTimeout()後にプロセ

スを強制終了してみる

• プロセスが⼀瞬で終わります

• 当然setTimeout内の処理も実⾏されず。。

Page 23: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

child_process

• Node.jsはchild_processモジュールを通じて親プロセス(メインストリーム)から⼦プロセスを⽣成することができます

• ⼦プロセスは親プロセスから切り離す事ができる!

Page 24: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

何が嬉しいのか• ⼦プロセスを親から切り離すことによって、親プロ

セスが死んでも⼦プロセスは動き続ける事ができるようになる

• 更にこの状態で⼦が親に対して、⾃分の処理終了を待たないように宣⾔する事ができる

• 通常は切り離したとしても親は⼦の終了を待つ

Page 25: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

実際のコード• spawnでOSコマンドを実

⾏できる

• detache: trueが切り離し命令

• unref()することで⼦の終了を待機しなくなる

• これで勝ったと思いきや…

Page 26: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

それ、Lambdaで 出来ないよ

Page 27: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

なぜなのか

• Lambdaではメインストリームの処理が終了した瞬間、派⽣する処理は全て殺されます

• なので前述の例で⾔うとunref()が実⾏された瞬間、親プロセスは以降の⾏に処理が無いのでそこで終了します

• = ⼦も終了します

Page 28: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

なので• こうしても同じです

• Node.js的には正しいですが、Lambda的には意図した動作になってくれません

• detachしてるので⼦プロセスは⽣き残れるはずですが、Lambdaではprocess.exit()によって⼦も殺されます

• 無念。。。

Page 29: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

X-Amz-Invocation-Type• Amazon API Gatewayの公式ドキュメントに下記

のような記述があります

要するに…

Page 30: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

API Gatewayのここの

Page 31: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

これに

これを

追加して下さい、ということです。

Page 32: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

しかし• やってはみるものの、⼀向に⾮同期にならない

• 10秒スリープするようなスクリプトを呼ぶと、ご丁寧に10秒待たされる

• API GatewayのLambdaに関連しそうなドキュメントは⼀通り⽬を通したが⼀向に謎は解けない

• ここでかなりハマる

Page 33: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

いろいろ試す• メソッドリクエストから統合リクエストに対して

ヘッダーをマッピングしなきゃいけない?

• X-Amz-Invocation-Type?XAmzInvocationType? x-amz-invocation-type?

• InvocationTypeはEvent?DryRun?

• POST/GET?

Page 34: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

時は流れ

• ふと初⼼に戻りLambdaの仕組みに⽴ち返る

• Lambdaの公式ドキュメントに衝撃の事実を⾒つける

Page 35: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。
Page 36: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

• LambdaはAPI Gatewayを⽤いたHTTPSを経由して実⾏される場合、常にRequestResponse(同期)の呼び出しタイプを使⽤します。

Page 37: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

ん?

• API Gateway側のドキュメントとLambda側のドキュメントで⽭盾が⽣じてる気がしなくもない

• とはいえ出来ないものは出来ないので仕⽅ない

• ということで最終⼿段

Page 38: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

Lambda => Lambda

• はい、LambdaからLambdaを呼びます

Page 39: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

イメージクライアント Gateway Lambda

200 OK

⾮同期

S3

Lambda

Page 40: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

実際のコード• Lambda上でaws-sdkを

⽤いたLambdaの⾮同期呼び出しを⾏えばよいことに気づく

• lambda.invokeAsync()がポイント

• InvokeArgsには受け取ったpayload(event)をそのままぶん投げる

Page 41: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

⾮同期化成功!

Page 42: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

まとめ

• Lambdaをうまく活⽤すればEC2いらずで経済的!

• HTTPS経由の⾮同期呼び出しは⼯夫すれば何とかなる!

Page 43: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

最後に

Page 44: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

ドキュメント読もう。ちゃんと。

Page 45: AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。

ご清聴ありがとうございました。