この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
AIソリューション部の平内(SIN)です。
Amazon Connectや、Amazon Alexaでは、Lambda関数を利用できますが、どちらもタイムアウトに制限(8秒)があり、時間内に処理できない場合、サービス側でエラーとなってしまいます。
このタイムアウトは絶対に避けることができないため、もし、処理時間が長くなる(若しくは、その危険性がある)場合、それを考慮した設計が必要になります。
下記は、実行時間が長い処理をSQSで処理するようにした例です。
Amazon ConnectとTwilioの連携
今回は、このような場合に、「何の処理に、どれ位時間がかかるので、このように設計しました」と明確に言うための資料としてX-Rayを簡単に使ってみたのでその記録です。
注:すいません。本記事は、X-Rayの特別な使い方を紹介するようなものではありません。利用手順をまとめただけの個人的な覚書です。
2 手順
今回作業した手順は、以下のとおりです。
- トレースの有効化
- aws-xray-sdk-coreの利用
- サブセグメントの生成(X-Ray対応外のファンクションを使用するため)
(1) トレースの有効化
Lambda関数からX-Rayを使用するには、デバッグとエラー処理のところで、アクティブトレースを有効にしますにチェックします。
(2) aws-xray-sdk-coreの利用
AWSのサービスをトレースするだけなら、aws-xray-sdk-coreでaws-sdkをラップするだけです。
const AWSXRay = require('aws-xray-sdk-core');
var AWS = AWSXRay.captureAWS(require('aws-sdk'));
(3) サブセグメントの生成
AWSのサービス以外をトレースしたい場合は、サブセグメントを生成して囲みます。
const seg = AWSXRay.getSegment();
const subsegment = AWSXRay.getSegment().addNewSubsegment('Twillo');
// ここに計測したいファンクションを記述する
subsegment.close();
3 対象コード
サンプルで準備したコードは、以下のようなものです。
Connectから呼び出されるLambda関数をイメージしています。
- 電話番号をDynamoDBに記録する
- メッセージ文の雛形をS3から取得する
- SMSを送信する(Twilio)
const AWSXRay = require('aws-xray-sdk-core');
var AWS = AWSXRay.captureAWS(require('aws-sdk'));
exports.handler = async (event) => {
const phoneNumber = event.phoneNumber;
// DynamoDBに電話番号を記録する
const tableName = 'x-ray-sample';
const promaryKey = phoneNumber;
const value = (new Date()).toString();
await dynamoDbPut(tableName, promaryKey, value);
// S3からSMSの本文取得する
const bucket = 'x-ray-sample';
const key = 'sms-message.txt';
const data = await s3GetObject(bucket, key);
const body = data.Body.toString("utf-8");
// TwilioでSMS送信する
const seg = AWSXRay.getSegment();
const subsegment = AWSXRay.getSegment().addNewSubsegment('Twillo');
const result = await createSMS(phoneNumber, body);
console.log(result);
subsegment.close();
};
async function s3GetObject(bucket, key) {
var s3 = new AWS.S3();
var params = {
Bucket: bucket,
Key: key
};
return await s3.getObject(params).promise();
}
async function dynamoDbPut(tableName, promaryKey, value) {
const client = new AWS.DynamoDB.DocumentClient();
let item = {
"id": promaryKey,
"value": value
}
var param = {
TableName : tableName,
Item: item
};
return await client.put(param).promise();
}
async function createSMS(to_number, body) {
const account_sid = process.env.Sid;
const auth_token = process.env.Token;
const from_number = process.env.FromNumber;
const client = require('twilio')(
account_sid,
auth_token
);
return new Promise( (resolve, reject) => {
client.messages.create({
from: from_number,
to: to_number,
body: body
})
.then(response => {
console.log(response);
resolve(response.id);
})
.catch( error => {
reject(error);
})
})
}
4 トレースの確認
X-RayのコンソールからTraceを選択し、適当な時間(過去、何分前までのものを検索対象とするか)を指定して更新すると、Traceリストに1回の実行が1行となって表示されます。
トレースを選択すると、その内容が確認できます。
TwilioのSMS送信処理で、12.3sかかっていることが分かります。この結果から、Twilioのレスポンスによって「送信しました/送信に失敗しました」のようなアナウンスを返す実装は不可能であることが分かります。
5 AWS_XRAY_CONTEXT_MISSING
実際の計測は、Lambdaの実行環境で行なうため、問題とならないのですが、デバッグ等のため、コードをローカルで実行しようとすると、下記のエラーが出ます。
Error: Failed to get the current sub/segment from the context.
このエラーは、AWS_XRAY_CONTEXT_MISSINGという環境変数が設定されていない事が原因のようです。
実環境で動作させると、LOG_ERRORという環境変数がセットされていることが確認できます。
console.log('AWS_XRAY_CONTEXT_MISSING=' + process.env.AWS_XRAY_CONTEXT_MISSING);
AWS_XRAY_CONTEXT_MISSING=LOG_ERROR
実際にローカルの実行環境で環境変数を設定するか、若しくは、下記のコードでこの問題を回避できます。
AWSXRay.setContextMissingStrategy('LOG_ERROR');
7 最後に
今回は、時間制限のある要件で、時間を要する処理があった場合に、その状況を把握して表現する方法としてX-Rayを使用してみました。
軽易に、使えるようにして、資料作成等に利用できるようしたいと思います。
8 参考リンク
ローカルで X-Ray デーモンを実行する
AWS X-Rayによるアプリケーションの分析とデバッグ
AWS Black Belt Online Seminar 「 AWS X-Ray」 資料及びQ&A公開
AWS X-Ray を使用する
AWS Lambda および AWS X-Ray