LoginSignup
27
15

More than 5 years have passed since last update.

AuroraへのInsert TriggerでLambdaを呼びだしてServerlessで処理する

Last updated at Posted at 2016-12-21

はじめに

要件

  • 世界展開を行うECシステムで、ネットワークレイテンシーを解消するために、AWSの各リージョンにフロントエンド機能を設置する。
  • 但し、個人情報は既存のDCに保管するものとして、ECで発生したオーダーデータ等の個人情報についても一定期間以上 AWSのDBに保持してはならない。
  • 尚、今回利用するECパッケージは、オーダーが入ると同一リージョンのオーダーテーブルにデータが登録される。

ソリューション

  • ECは、パッケージ利用想定なので、なるべくイジらないのがセオリー。
  • で、オーダーテーブルに登録されたレコードを普通に移動させれば良いので、以下の構成は普通に思いつくわけです。

ec architecture1

  • 上記だと、いかんせんサーバレスじゃないので、以下のような構成が発案されます。

ec architecture2

  • しかしながら、上記だと赤丸部分でオーダーと同時にSQSにメッセージ投げるというECパッケージの改修が必要となるのでゲンナリします。(これを通すと先輩の手を煩わせることに...)
  • 結合度も高いので、疎結合なサーバレスアーキテクチャとして、以下のような構成が発案されます。
  • 因みにRDSのエンジンは、良いことしかないのでAuroraにしましょう。

ec architecture3

テーブルへのInsert通知をServerlessで処理する

  • 上記を踏まえてテーブルへのInsert通知をServerlessで処理する方法を紹介します。
  • 具体的には、オーダーテーブルへのAfter InsertにTrigger仕込んで、Lambda経由でSQSにメッセージを登録する方法になります。
  • SQSに伝わればその先は幾らでもやりようがあると思います。
  • Triggerは、複雑過ぎると良いことないので、シンプルに使いましょう。

ec architecture4

IAM Roleを作成する

  • Lambda用Role
項目 設定内容
ロール名 (任意:[例] LambdaDbTriggerTestRole)
AWS サービスロール AWS Lambda
アタッチするポリシー AmazonSQSFullAccess
  • RDS用Role
項目 設定内容
ロール名 (任意:[例] RdsDbTriggerTestRole)
AWS サービスロール AWS RDS
アタッチするポリシー 無し
※超重要※ 作成後、アクセス許可タブでAWSLamdbaRoleをアタッチ

SQSでQueueを作成する

  • 任意のキュー名でキューを作成します。
  • 例)DbTriggerTestQueue

LambdaでFunctionを作成する

  • RDSからキックされ、SQSにメッセージ送信するLambdaファンクションを作成します。
項目 設定内容
Runtime Python 2.7
Handler lambda_function.lambda_handler
Role 先程作成したLambda用Role
  • コードは以下の内容です。(queueNameは、先程作成したqueueNameを指定してください)
main.py
import boto3
import json
import logging

queueName='DbTriggerTestQueue'

def lambda_handler(event, context):
  try:
    logger.info(event)
    response = boto3.resource('sqs').get_queue_by_name(
      QueueName = queueName
    ).send_message(
      MessageBody = json.dumps(event)
    )
    logger.info(response)
    return response

  except Exception as e:
    logger.error(e)
    raise e

Auroraを起動する

  • 以下の内容で起動しました。
項目 設定内容
リージョン ap-northeast-1
インスタンスクラス db.t2.medium
マルチAZ No
サブネットグループ Default
パブリックアクセス可能 No
Availability Zone ap-northeast-1a
パラメータグループ 新規のDB Parameter Group
新規のDB Cluster Parameter Group

AuroraにIAMロールを設定する

  • クラスターのIAMロールの管理から先程作成したRDS用Roleを紐付けます。

skitch.4.png

  • 先程作成&Auroraに指定したDB Cluster Parameter Groupのパラメータの編集から、aws_default_lambda_roleの値に、先程作成したRDS用RoleのARNを設定します。
  • 例)arn:aws:iam::xxxxxxxxxx:role/RdsDbTriggerTestRole

skitch.6.png

  • DBクラスタパラメータグループがpending-rebootになるはずなので、Auroraを再起動します。

Triggerを作成する

  • 再起動したらAuroraに接続して、以下のStored Procedure、Table、Triggerを作成します。

  • Stored Procedure
    • mysql.lambda_asyncの第一引数は、先程作成したLambdaのARNを設定します。
sqs_order_data_ai_message.sql
DROP PROCEDURE IF EXISTS sqs_order_data_ai_message;
DELIMITER ;;
CREATE PROCEDURE sqs_order_data_ai_message (IN id INT(11), 
                                      IN item VARCHAR(50)) LANGUAGE SQL 
BEGIN
  CALL mysql.lambda_async('arn:aws:lambda:ap-northeast-1:xxxxxxxx:function:TestFunction',  
    CONCAT('{ "id" : "', id, 
            '", "item" : "', item, '" }')
     );
END
;;
DELIMITER ;
  • Table
order_data.sql
CREATE TABLE `order_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `item` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • Trigger
trigger_order_data_ai.sql
DELIMITER ;;
CREATE TRIGGER trigger_order_data_ai 
  AFTER INSERT ON order_data 
  FOR EACH ROW
BEGIN
  CALL sqs_order_data_ai_message(NEW.id, NEW.item);
END
;;
DELIMITER ;

動作テスト

  • 以下のSQLを実行してみます。
insert.sql
INSERT INTO order_data VALUES (NULL, 'item_001');
  • 取り急ぎ、SQSの画面で利用可能なメッセージがカウントアップされていれば成功です。

skitch.7.png

備考

  • エンジンはAurora一択です。MySQLを選んだところで以下のようにmysql.lambda_asyncがコール出来ないです。
MySQL
mysql> show create procedure mysql.lambda_async \G
ERROR 1305 (42000): PROCEDURE lambda_async does not exist

参考

27
15
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
15