AWS re:Invent 2014で発表された新サービスAWS Lambda。 先日Limited Previewの申請が通ったので早速Lambda使って何かできないかと思い、Webサイトの監視をLambdaを使って実現してみました。

5分間隔で指定したサイトを監視し、400、500系のレスポンスが帰ってきた場合は、SNSに異常状態である旨メッセージ通知をします。

LambdaはS3上のファイルの変更やKinesisに届いたメッセージ、DynamoDBへのデータの更新といったイベントに反応して任意のコードを実行できるプラットフォームです。Lambda自体に定時処理を行うような仕組みは用意されていないので、Lambda Function内部でS3にオブジェクトをPUTすることでLambda Functionの実行をループします。

処理は↓のステップで行います。

  1. site-監視時刻ミリ秒(例:site-1418090313922)といった命名規則のファイルを用意し、以下のように監視したいURL記載しておきます。
    https://haws.haw.co.jp/
    ../../%3C/pre%3E
    
  2. S3に上記ファイルがPUTされたトリガーでLambda Functionを実行
  3. 対象ファイルの時刻をパースして監視時刻を出し、現在時刻より過去であればサイトチェック。現在時刻より未来であればまだ監視タイミングではないので対象のファイルのタイムスタンプを更新(2に戻る)。
  4. サイトチェックし400以上のステータスコードが帰ってきた場合は、SNSに通知。
  5. ファイル名に含まれる監視時刻を5分追加したファイル名でファイルを置き換え。
Lambdaの設定

新規にLambda Functionを作成します。Lambda Function Nameに任意のFunction名を入力し、Lamda Functionのコードを貼り付けます。(ライブラリを利用するケースは、ZIPアップロードも可能)
続いて、Lambda Functionに反応する関数名をHandler nameに定義し、このLambda Function実行時に与えるIAM Roleの設定します(今回はS3へのGET/PUT/DELETE権限と、SNSのPublish、CloudWatch Logsの権限を付加)。
最後に使用するメモリとタイムアウトの秒数を設定。

createlambda

実際に設定したコードは↓。

var http = require('http');
var AWS = require('aws-sdk');

exports.handler = function(event, context) {
  var bucket = event.Records[0].s3.bucket.name;
  var key = event.Records[0].s3.object.key;
  console.log("bucket : " + bucket + ", key : " + key);
  var monitorTime = parseInt(key.split("-")[1]);
  var currentTime = new Date().getTime();
  var s3 = new AWS.S3({region: 'us-west-2'});
  if(monitorTime < currentTime) {
    s3.getObject({Bucket: bucket, Key: key}, function(err, data){
      if(err) {
        console.log('error get object ' + key, err);
        context.done('error', err.stack);
      } else {
        var urls = data.Body.toString().split("\n");
        for(var i=0; i

Lambda Functionの作成が終わると、ダッシュボードでLambda Functionを選択して「Configure event source」を選択して、S3にファイルがPUTされた際にLambda Functionが実行されるよう対象のBucketの設定と、Lambda Functionを起動すめのInvocation Roleを作成/選択します。

lambdaconfigure

ここで設定するBucketはLambda Functionと同じリージョンのBucketである必要があります。

実行状況

あとは、監視サイトを定義したファイルを対象のBucketにアップロードするとLambda Functionが起動します。Lambda Functionの実行ログはCloudWatch Logsに送信されているので、CloudWatch Logsのコンソールで↓のように確認できます。
lamdalogs
またLambdaのダッシュボードでLambda Functionの実行状況が確認できます。
lambdadashboard

まとめ

Lambdaを利用することで、実行プラットフォームのことを意識する必要なくプログラムを動作させることができるのは大きなメリットだと感じます。いかにEC2を使わずにスケーラブルなプラットフォームを構築するか考える上で、とても魅力的な要素です。

個人的にはS3やKinesis、DynamoDBのトリガー以外にLambda自体が定期処理をサポートしてくれるといろいろ用途が広がって良いかと思います。Data Pipelineのスケジューラと組み合わせると、よりcronライクなトリガーになって面白いかも。(Data Pipelineのスケジュールの最小間隔は15分なのでそんなに細かい時間帯での設定はできませんが。)

またJavaScript以外にRubyサポートも!