AWS LambdaでWebサイトの死活監視(後編)

前回の続きです。

Webサイトの死活監視で、一回前にアクセスした結果を保存し、それと比較する方法を考えてみます。

一回前にアクセスした結果をどのように保存するかですが、正攻法で行くと S3 や DynamoDB へアクセス結果を保存(永続化)することが考えられます。
ただ、それらを使用せずLambda内で完結することができればよりシンプルになりますね。

まず実験として、次のコードをLambdaで実行してみます(言語: Node.js 4.3)。

'use strict';

let x = true;

exports.handler = (event, context, callback) => {
    x = !x;    // true,falseを反転
    console.log('x:' + x);
};

1回実行すると「x:false」とログに表示されます。これは当然です。
これをすぐに続けて再実行してみると、「x:true」とログに表示されます(!)。

この挙動は、
http://www.slideshare.net/keisuke69/aws-lambda-46129981
のスライド42-45にある、コンテナの再利用によるものと考えられます。

(ちなみに上記のコードを更新してから実行すると初回は必ず「x:false」となります。これは、コンテナが新たに作成されているためと考えられます。)

実行からある程度時間が経過して再実行する場合は新たにコンテナが作成されるようですが、今回は(5分間隔などの)短い時間ごとに実行しますので、この仕組みを利用してみることにします。
ただし、コンテナが再利用される保証はありませんので、この仕組みを使う場合、あくまで自分用に使用することをお勧めします。

ということで、Webサイト死活監視のバージョンアップ版が下記になります(言語: Node.js 4.3)。

'use strict';

let aws  = require('aws-sdk');
let http = require('http');    // https の場合は require('https')

let snsParams = {
    TopicArn: 'arn:aws:sns:xxx'    // AWS SNSのトピックARN
    ,Subject: 'AWS SNS alert from Lambda'
};

let url = 'http://xxx';    // 監視するWebサイトのURL

let prevStatus = 'OK';    // 前回のアクセス結果

exports.handler = (event, context, callback) => {

    function statusChange(nowStatus, errMessage) {
        console.log('prevStatus: ' + prevStatus);
        console.log('nowStatus: '  + nowStatus);
        if (prevStatus !== nowStatus) {
            snsParams.Message = 'Website Status Change'
            + ' [ ' + prevStatus + ' -> ' + nowStatus + ' ]: '
            + url + ' ' + errMessage;
            console.log(snsParams.Message);
            prevStatus = nowStatus;
            (new aws.SNS()).publish(snsParams, (err, data) => {
                if (err) console.log(err.stack);
                else     console.log(data);
            });
        }
    }

    http.get(url, (res) => {
        res.on('data', () => {});
        res.on('end', () => { statusChange('OK', ''); });
    }).on('error', (e) => { statusChange('NG', e.message); });
};

このLambdaをCloudWatchのスケジュールで一定時間ごと(5分ごとなど)に実行するようにします。
アクセス成功/失敗が変化した場合に、AWS SNS経由で通知が行われます。