3
1

More than 5 years have passed since last update.

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

Posted at

はじめに

この記事は 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することができます。
ではまた!

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1