[AWS×Node.js] AWS Lambda(Node.js)で他のサービスと連携する(2018年版)

[AWS×Node.js] AWS Lambda(Node.js)で他のサービスと連携する(2018年版):


はじめに

この記事は AWS Advent Calendar 2018 の7日目の記事です。

去年のアドベントカレンダーで「AWSLambdaとその他のサービスを組み合わせていろんなことをしてみる」という記事を書いたのですが、今年も1年間でLambdaのアップデートがあったので、2018年版という形で記事を書いていきます。


AWSLambdaアップデートまとめ

今年あったLambdaのアップデートの中で個人的に印象が強かったものを上げてみます。


  1. Node.js v8.10 に対応

  2. Golang に対応
  3. 実行時間が 最大15分 に延長
といった感じです。

この他にもre:Inventで様々なアップデートがありましたね!

ランタイムにRubyを選択できるようになったり、CustomRuntimeで様々な言語をサポートしたり、ALB経由でinvokeできるようになったりと、まだまだLambdaは進化していくんだなと実感しました。


1. Node.js v8.10に対応

Node.jsユーザーの私からすると、Node.js8系への対応はかなり嬉しいものがありました。

なんと言っても async/await をLambdaでつ使えることで、非同期処理周りの書き方がとても楽になりましたね。

これについては「AWS LambdaがNode.js8.10をサポートしたのでasync/awaitを試してみた」でまとめてますので、よかったら見てあげてください。

今回の記事はNode.js v8.10で他のサービスと連携する内容を深掘りしていこうと思います。


2. Golangに対応

ちょっとGolangに興味があった時期にこのアップデートがあったので、試しに触ってみました。

AWSLambdaがGo言語に対応したのでDynamoDBと絡ませながらデモってみた」でまとめてますので、よかったら見てあげてください。

DynamoDBに対して、GetItem / PutItem / Queryを実行しています。


3. 実行時間が最大15分に延長

今まで5分が最長だった実行時間が15分に延長されました。

これによって、より長くLambdaの中で処理を実行することができるようになったので、ちょっとしたバッチ処理などを実行させるのに有効かと思います。

ですが、個人的にはLambdaの中であまり長い処理を実行することはおすすめできません。


他のサービスと連携する

AWSLambdaを単体で利用される方はほとんどいないと思います。

LambdaからS3にテキストを保存したり、DynamoDBのデータを操作したり、SESやSNSのトリガーになったり……といろんなサービスと連携すると思います。

今回はS3 / DynamoDB / SES と連携する際のNode.jsの書き方をまとめていきます。


S3

S3とはゴミ箱…ではなく、安価で高可用性なファイルストレージです。

主にテキストや画像データを保存するのに適しています。S3に保存しておくと、自動的に3箇所に複製されます。また、保存されているファイルに対してURLが付与されるので、取り出すのにもハードルが低いのが特徴です。


ファイルを取得する(getObject)

"use strict"; 
const AWS = require("aws-sdk"); 
const S3 = new AWS.S3(); 
 
exports.handler = async (event, context, callback) => { 
  try { 
 
    // パラメータ生成 
    const getParams = { 
      Bucket: "BucketName", 
      Key: "objectKey.json" 
    } 
 
    // S3にGETするSDK(API)実行 
    const obj = await S3.getObject(getParams).promise(); 
 
    return obj; 
  } catch (err) { 
    throw err; 
  } 
}; 


ファイルを保存する(putObject)

"use strict"; 
const AWS = require("aws-sdk"); 
const S3 = new AWS.S3(); 
 
exports.handler = async (event, context, callback) => { 
   try { 
 
    // JSON文字列作成 
    const jsonFile = [{ 
      id: "12345", 
      value: "1111" 
    },{ 
      id: "67890", 
      value: "2222" 
    }]; 
 
    // パラメータ生成 
    const purParams = { 
      Bucket: "BucketName", 
      Key: "sample.json", 
      Body: JSON.stringify(jsonFile) 
    } 
 
    // S3にPUTするSDK(API)実行 
    await S3.putObject(purParams).promise(); 
 
    return null; 
  } catch (err) { 
    throw err; 
  } 
}; 


DynamoDB

DynamoDBはNoSQLのデータベースです。SQL文を生成してデータを操作するのではなく、API経由でデータの操作を行います。

今年はデータのバックアップ機能(PITR)やグローバルテーブルなどの大型アップデートがあったりと、最近Hotなサービスの一つです。


想定テーブル

テーブル名: sensorDataTable

sensor_id record_time value
a001 2018-12-07T00:00:00+09:00 10
a001 2018-12-07T00:10:00+09:00 17
a001 2018-12-07T00:20:00+09:00 20
a001 2018-12-07T00:30:00+09:00 14
a001 2018-12-07T00:40:00+09:00 10


データを取得する(query)

"use strict"; 
const AWS = require("aws-sdk"); 
const dynamoDB = new AWS.DynamoDB.DocumentClient(config); 
 
exports.handler = async (event, context, callback) => { 
  try { 
    // パラメータ生成 
    // テーブル sensorDataTable に対して sensor_id が a001 のデータを 
    // record_time が 2018-12-07T00:00:00+09:00から昇順で100件取得する 
    const params = { 
      TableName: "sensorDataTable", 
      KeyConditionExpression: "#hash_key = :hash_key AND #range_key >= :range_key", 
      ExpressionAttributeNames: { 
        "#hash_key": "sensor_id", 
        "#range_key": "record_time"  
      }, 
      ExpressionAttributeValues: { 
        ":hash_key": "a001", 
        ":range_key": "2018-12-07T00:00:00+09:00" 
      }, //  
      ScanIndexForward: true, // データの参照を昇順でするか、降順するか。 true: 昇順 / false: 降順 
      Limit: 100 // 取得するレコード数の上限 
    }; 
 
    // DynamoDBからデータを取得するSDK(API)実行 
    return await dynamoDB.query(params).promise(); 
  } catch (err) { 
    throw err; 
  } 
} 


データを保存する(put)

"use strict"; 
const AWS = require("aws-sdk"); 
const dynamoDB = new AWS.DynamoDB.DocumentClient(config); 
 
exports.handler = async (event, context, callback) => { 
  try { 
    // パラメータ生成 
    // テーブル sensorDataTable に対して sensor_id が a001 のデータを保存する 
    const params = { 
      TableName: "sensorDataTable" 
      Item: { 
        sensor_id: "a001", 
        record_time: "2018-12-07T12:00:00+09:00", 
        value: 25 
      } 
    }; 
 
    // DynamoDBからデータを保存するSDK(API)実行 
    return await dynamoDB.put(params).promise(); 
  } catch (err) { 
    throw err; 
  } 
} 


SES

SESはメールを送信してくれるサービスです。

S3やDynamoDBに比べると使用する場面は少ないと思いますが、私はよく利用しています。

"use strict"; 
const AWS = require("aws-sdk"); 
const ses = new AWS.SES; 
 
exports.handler = async (event, context, callback) => { 
  try { 
    // パラメータ生成 
    // テーブル sensorDataTable に対して sensor_id が a001 のデータを保存する 
    const params = { 
      Source: "from_address@hoge.com", 
      Destination: { 
        ToAddresses: ["to_address@fuga.com"] 
      }, 
      Message: { 
        Subject: { 
          Data: "メールのタイトル" 
        }, 
        Body: { 
          Text: { 
            Data: "メールの本文" 
          } 
        } 
      } 
    }; 
 
    // メールを送信するSDK(API)実行 
    return await ses.sendEmail(params).promise(); 
  } catch (err) { 
    throw err; 
  } 
} 


まとめ

今回はLambdaからその他のサービスと連携するサンプルをまとめました。LambdaはAWSの他のサービスとの親和性がかなり高いサービスです。S3やDynamoDBなどのデータレイクに格納する前にちょっと加工したり、SESなどのトリガーになったりします。

AWSLambdaは直接invokeしようとするとクレデンシャルを持たせないといけないのですが、Lambdaの前段にAPIGatewayを挟むこととで、Lambdaをinvokeするためのクレデンシャルを持たずにinvokeすることができます。

ではまた!

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)