AWS Lambda
AWS Lambda
「API Gateway Lambda プロキシ統合」を使うと API 開発が捗りそうな話
- reference
- わかったこと
- 意義
- 自由度が高くなる(反面、一部では大変になる予感も…まだ予感だけ)
- API Gateway が Lambda を呼び出す際に、 HTTP リクエストに含まれている情報を連携するために、よくわからない
Mapping Template
を作成する手間から解放される - コレを使うと API request の内容を raw な感じで Lambda が受け取れる
- コレを使うと lambda からの レスポンスが直接 API response を細かく定義できる (http status code とか)
- 使い方
- APIGW 側で
統合リクエスト
画面からAPI Gateway Lambda プロキシ統合
にチェックを入れて有効化 - Lambda 側応答
- 以下の JSON 形式にする必要があり、それを守らないと
502 Bad Gateway
になる{ "isBase64Encoded": true|false, "statusCode": httpStatusCode, // 必須 "headers": { "headerName": "headerValue", ... }, "body": "..." // JSON を返したければ JSON.stringify(object) とすれば良い }
- 以下の JSON 形式にする必要があり、それを守らないと
- APIGW の Lambda への input
- API Gateway は受信リクエストを Lambda 関数の入力
event
パラメーターにマッピングする。入力にはリクエストメソッド、パス、ヘッダー、クエリパラメーター、ペイロード、関連コンテキスト、定義済みステージ変数が含まれています。{ "resource": "Resource path", "path": "Path parameter", "httpMethod": "Incoming request's method name" "headers": {Incoming request headers} "queryStringParameters": {query string parameters } "pathParameters": {path parameters} "stageVariables": {Applicable stage variables} "requestContext": {Request context, including authorizer-returned key-value pairs} "body": "A JSON string of the request payload." "isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode" }
- 受け取る Lambda 側も注意は必要で、
event.body
が JSON ではなく、テキスト文字列になっているので、JSON.parse
してやる必要があるのを忘れずに。
- API Gateway は受信リクエストを Lambda 関数の入力
- APIGW 側で
- 意義
Lambda timeout に注意!
とある試験結果を見ていて、「うおーなんぞこの502 bad gateway!」と思って本気で悩んでたら、serverless でデプロイする Lambdaの default timeout が 6.00 sec という罠を見つけた… https://github.com/serverless/serverless/issues/2640 serverlessじゃないLambdaは3secに見えてるよ…おぞましいいい Gatlingからエラーのときにdebugログ(req/res詳細の出力)みて、headerにある
x-amzn-RequestId
みて、 cloudwatch でそのIDでログ全部引っ掛けて…2018-06-12T04:15:47.092Z 44a406b6-6df7-11e8-8f4e-81b9f60f44ab Task timed out after 6.00 seconds
というログにたどり着くというデバッグ手順 (edited)
Lambda の良い開発フローの検討
Serverless Framework+Node.jsで普通に設計する Serverless Framework+Node.jsをつかったLambda関数の開発フロー を読みながら採用するものを検討
- デプロイ/パッケージング: Serverless Framework に決定
- ビルド: 結局いまのところ何も使っていない
- Babel: 最近の js 開発者は ES6 とか ES2017 とか使うんだけど、 IE11とかの互換性がだめなのです。古めのES5などにコードを変換・コンパイル(トランスパイルと呼ぶ人もいた)するのが Babel
- webpack: Babel はパッケージの管理まではできないようで、その面で Babel をサポートするのが webpack らしい
- 開発効率系
- AVA: テストフレームワークっぽい。非同期で複数テストを処理してくれるらしく、良さげ
- mocha: AVAじゃなくてこれ使ってる
- istanbul: test coverage を可視化するもの。良い。使ってる。
- Flow
- eslint: 使ってる
- yarn
- その他
- axios/bluebird/lodash/momentなど
Lambda ランタイムの調査
ランタイムごとの動きとかについてまとめるよ
nodejs10.x の cloudWatchLogs 出力のクセ (2019/05/19 現在)
今まで console.log(JOSN.stringify(hogehoge, null, 4))
が1エントリーになっていたのに、 nodejs10.x では改行ごとに別エントリーになってしまうのを発見! (2019/05/19 時点)
そこで、ちょっと丁寧にランタイムバージョンごとに動作比較をしてみた。
nodejs6.10 with linebreak
- コード
exports.handler = (event) => { // TODO implement const response = { statusCode: 200, body: JSON.stringify('nodejs6.10 with linebreak'), }; console.log(JSON.stringify(response, null, 4)); return response; };
- ログ: ちゃんと JSON オブジェクトがひとかたまりで記録され、シンタクスハイライトも動いています
- コード
nodejs6.10 without linebreak
- コード
exports.handler = (event) => { // TODO implement const response = { statusCode: 200, body: JSON.stringify('nodejs6.10 wo linebreak'), }; console.log(JSON.stringify(response)); return response; };
- ログ: これもOK
- コード
nodejs8.10 with linebreak
- コード
exports.handler = (event) => { // TODO implement const response = { statusCode: 200, body: JSON.stringify('nodejs8.10 with linebreak'), }; console.log(JSON.stringify(response, null, 4)); return response; };
- ログ: これもOK
- コード
nodejs8.10 without linebreak
- コード
exports.handler = (event) => { // TODO implement const response = { statusCode: 200, body: JSON.stringify('nodejs8.10 without linebreak'), }; console.log(JSON.stringify(response)); return response; };
- ログ: これもOK
- コード
nodejs10.x with linebreak
- コード
exports.handler = (event) => { // TODO implement const response = { statusCode: 200, body: JSON.stringify('nodejs10.x with linebreak'), }; console.log(JSON.stringify(response, null, 4)); return response; };
- ログ: おやおや、 JSON オブジェクトがちぎられてしまっている!!!
- コード
nodejs10.x without linebreak
- コード
exports.handler = (event) => { // TODO implement const response = { statusCode: 200, body: JSON.stringify('nodejs10.x without linebreak'), }; console.log(JSON.stringify(response)); return response; };
- ログ: おお、元通りです。
- コード
結論: この動作は改修されるかもしれないけれど、もともと JSON.stringify で改行無しで出力していればよしなに表現してくれるので、それをやれば良さそうです