Lambda単体とかEC2とかECSは普通に使っていたが、試そうと思っていたが出来ていなかったサーバレス関係のメモ。
ここを主に参考にする。
ServerlesFrameworkを使えば楽なのかもしれないが、理解するためにもIaC関係は使わずに手で設定
DynamoDB
AWSのコンソール画面でDynamoDBを開いて「テーブルの作成」を選択。
テーブル名:TestTable
パーティションキー:DeviceID
ソートキー:SensorID
で、残りはデフォルトで作成。
作成したテーブルに対して項目追加でレコードを作成すると同時にvalue, unitの項目作成。
適当にテスト用レコードを作成
Lambda
LambdaからDynamoDBを操作できるようなIAMロールは必要。
AmazonDynamoDBFullAccess
AWSLambdaDynamoDBExecutionRole
をテストのためにアタッチしておいた。
PythonよりJavaScriptの方が慣れているのでnodejs(Node.js 14.x)で作成する。
DynamoをLambdaから扱う場合、AWS.DynamoDBとAWS.DynamoDB.DocumentClientがあるが、DocumentClientを使う方が楽
単純にキーで引っ掛けて検索
var params = {
TableName: "TestTable",
Key:{
DeviceID: "Dev0001"
}
};
docClient.get(params, function(err, data){
if(err){
console.log(err);
}else{
console.log(data.Item);
}
});
追加
var params = {
TableName: "TestTable",
Item:{ // キーが必ず必要
DeviceID: "Dev0003",
SensorID: "Temp001",
value: 30,
unit: "c"
}
};
docClient.put(params, callback);
削除
var params = {
TableName: "TestTable",
Key:{ // キー指定
DeviceID: "Dev0003",
}
};
docClient.delete(params, callback);
条件を複雑にしたクエリ
var params = {
TableName: 'TestTable',
ExpressionAttributeNames:{'#va': "value"}, // 予約語とか数値始まりは別名が必須
KeyConditionExpression: '#va <= :val', // 条件指定
ExpressionAttributeValues:{':val': 20} // 引数
};
// クエリの実行
docClient.query(params, function(err, data){
if(err){
console.log(err);
}else{
data.Items.forEach(function(devices, index){
console.log(devices.DeviceID);
});
}
});
条件には
- #x BETWEEN :min AND :max
- begins_with (#x, :str)
のようなものも存在する。
今回は単純なテストを行いたいだけなのでqueryを使った以下のようなものを作成
var AWS = require('aws-sdk');
var documentClient = new AWS.DynamoDB.DocumentClient();
var response = {
statusCode: 200,
headers: {},
body: ""
};
exports.handler = async function(event, context) {
// keys:[{"DeviceID":"xxx"},]
// 内部的には複数返すようにしていない
for (let key of event.keys) {
var device_id = key.DeviceID;
var param = {
TableName : "TestTable",
KeyConditionExpression: "#id = :val1",
ExpressionAttributeNames:{ // 予約語の場合もあるので別名の割り当てが可能
"#id": "DeviceID"
},
ExpressionAttributeValues: { // 引数。今回はソートキーは指定していない
":val1":device_id
}
};
// awaitでpromiseが返ってくるのを待つ
await documentClient.query( param, function( err, data ) {
if (err) {
response.statusCode = 500;
response.body = err;
} else {
response.body = data;
}
} ).promise();
return response;
}
};
Lambda関数が用意できた。
LambdaにGET/PUTを渡すようにAPIGatewayで設定してやることも出来るが
メソッド単位にLambdaのスクリプトを作成するのが(処理速度も若干望めるので)一般的のようである。
API Gateway
このlambdaをCallするためのAPIGatewayを画面から設定する。
適当にDynamoTestというAPIを作成して、GETメソッドを追加。
(GETにする場合はスクリプト側のキーの取り方を変更)
- メソッドリクエストの必須パラメータとしてクエリパラメータdevideを追加
- 統合リクエストのapplication/jsonで以下を追加
{
"keys": [{"DeviceID":"$input.params('device')"}]
}
(回りくどいやり方になってしまったが、テストになってのでよし)
テスト実行してみるとLambdaから返ってきた値が結果に表示された。
実際につかう場合はデプロイする事で反映される。
今回は自分用のテストなのでデプロイはしない。
APIキーを発行して利用を制限する事も可能