dynamodb(ログ)↔lambda(読み書き処理) ↔api gateway(APIサーバ) ↔S3静的ホスティング(html+ajax+post)で、サーバレス掲示板を作ってみた。伝統的なLAMPとは、色々と違う感じ!
0, dynamodbで掲示板ログテーブルを作る
まず、awsコンソールからテーブルを作る
テーブル設計は、MySQLと違ってカラムという概念がなく、キーを1個(パーティションーキー) or +2個目(ソートキー)を決めるだけ。
感覚的には、エクセル・CSV・KVSっぽい。DBっていうよりも、JSON形式で色々と放り込めるKVSってのが正しい理解?
(テーブル名=bbs, パーティションーキー=message, ソートキー=post_dateの3項目だけ入力)
Insertは項目の追加ボタンから、カラムを毎回追加する必要がある。(user_idを追加して、値を123とか)
dynamodbはauto_incrementがないので、とりあえず1から手動で追加したりとか、ユニークキーみたいなのは無いみたい。
Select文は、以下の3種類から選ぶ
Scan:全件取得
GetItem:条件に合う0〜1件取得
Query:いわゆるwhere句で、条件に合う0〜n件取得
1, lambdaで、レコード追加&全件取得できるようにする。
Lambdaがdynamodbを操作できるように、ロールとして、AmazonDynamoDBFullAccessポリシーを付与しておく(demo-lambda-roleとか適当に名前つけておいて、lambda関数の作成時に割りあげる)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
var AWS = require('aws-sdk'), documentClient = new AWS.DynamoDB.DocumentClient(); exports.handler = function( event, context, callback ) { // メッセージが空なら、過去ログを返すだけ if(event.message == ''){ get_all_message(); // メッセージ有りなら、dynamodbに追加してから、過去ログを返す }else{ const params = { TableName: 'bbs', Item: { post_date: now_timestamp(), message: event.message } }; documentClient.put(params, function (err, data) { if (err) { console.log(err); } else { console.log(data); get_all_message() } }); } // dynamodbになる過去ログ全件を返す。 function get_all_message(){ documentClient.scan( { "TableName": "bbs" }, function( err, data ) { if(err){ console.log(err); callback(null, err); }else{ // scan(全件取得)ではsort出来ないので、ここでソートする data.Items.sort(function(a,b){ if(a.post_date < b.post_date) return 1; if(a.post_date > b.post_date) return -1; return 0; }); callback(null, data.Items); } }); } // 現在日時を返す function now_timestamp(){ // lambdaの環境変数に、TZ=Asia/Tokyoを追加しておく const date = new Date(); return date.getFullYear() + '-' + ('0' + (date.getMonth() + 1)).slice(-2) + '-' + ('0' + date.getDate()).slice(-2) + ' ' + ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2) + ':' + ('0' + date.getSeconds()).slice(-2); } }; |
2, api gatewayでネットからpost出来るようにする
やる事その1、postメソッドで、さっき作ったlambda関数をルーティングする
やる事その2、CORSの有効化で、どこからでもPOST出来るようにする
やる事その3、APIのデプロイで、ネットからアクセス出来るようにする
3, S3静的ホスティングにindex.html(html+ajax+post) をアップロードして、ブラウザから入出力できるようにする。
post先は、APIのデプロイした時に表示される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<html lang="ja"> <head> <meta charset="UTF-8" /> </head> <body> <input type=text id="post_message" size=50 placeholder="何か投稿してみて!"> <button id="btn">投稿</button> <div> <div id="message"></div> </div> </body> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script type="text/javascript"> $(function() { function get_data(){ $.ajax({ // apiゲートウェイでデプロイした時に表示されるエンドポイントのURL url: 'https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/demo', type: 'POST', data: JSON.stringify({ "message": $("#post_message").val() }), dataType: "json", success: function(json) { let str_message = ""; for(i=0; i<json.length; i++){ str_message += json[i].post_date + " " + json[i].message + "<br>\n"; } $('#message').html(str_message); $("#post_message").val(""); }, error: function(err) { alert(err.message); }, }); } $("#btn").click(function(){ get_data(); }); // ロード時に投稿ログを画面に表示 get_data(); }); </script> </html> |
初めてサーバレス開発してみたけど、わりと細かいルールというか前提が色々と違って、伝統的なLAMPとは勝手が違う感じ。
そして、lambdaで読み書き処理が遅いな、と思ったら5分使われないとメモリから外されて、再ロードが必要になるのか…。
リアルタイムが必要なわけじゃないけど、遅延が気になるレベルだな。