AWS Lambda

Page content

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) とすれば良い
          }
          
      • 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 してやる必要があるのを忘れずに。

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.10wlb

  • 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 nodejs6.10wolb

  • 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.10wlb

  • 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 nodejs8.10wolb

  • 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.xwlb

  • 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;
      };
      

     - ログ: おお、元通りです。 nodejs10.xwolb

結論: この動作は改修されるかもしれないけれど、もともと JSON.stringify で改行無しで出力していればよしなに表現してくれるので、それをやれば良さそうです