はじめに
先日、AWSのLambdaとSQSを用いた、サーバーレスな設計で、あるアプリケーションを作成したので、その時のアーキテクチャや、実装面で工夫した点をまとめました!
基本的なアーキテクチャですが、前提知識が少し必要なので、やや中級者向けの記事になります!
こういう処理を走らせたいけど、お金がかかるしサーバーを動かし続けたくないなあ、、
という方は、ぜひlambdaを活用してみてはいかがでしょうか!
アプリの概要
作成したアプリは、大枠では下記の処理を順番に実行するものです。
- 処理する対象のURL一覧を取得する処理
- URLに登録されている文章を取得する処理
- 文章を要約する処理
- 要約された文章を、S3に登録する処理
周期を設定したEventBridgeをトリガーとして、この処理を開始します。
2番目以降の処理から、lambdaの同時実行の力とSQSの特性を活かして、並行処理を実施します。
アーキテクチャ
処理の詳細
1の処理の最後に、URLを1つずつQueueに格納する処理にすることで、URL単位でメッセージを送信することができ、その後の処理をメッセージ単位(URL単位)で実施することができます!
あまり触れたことない方はイメージしづらいかもしれませんが、例えば、100件のURLを処理する必要がある場合、URLを100件取得し、メッセージに登録する最初の処理は100回ループする必要があります。
しかし、その後の処理は、100件のURLを、100個のlambdaで並行処理することができるようにしています。
よくあるSQSの使用方法ですね!
コードの例
SQSにアクセスし、情報をQueueに格納する処理の参考コードは以下になります!
YOUR_ACCESS_KEY_IDなどの情報は、別途lambdaの環境変数の設定画面から設定する必要があります!
from sqs_connect import post_queue
def handler(event, context):
# 今回はURLリストを取得するメソッドは割愛
url_list = get_url_list()
#SQS送信
for url in url_list:
post_queue(url)
import boto3
import json
import os
import logging
def post_queue(url:str):
#json形式なので、dicに入れる
data_for_sqs = {"url": url}
#jsonに変換
message = json.dumps(data_for_sqs, ensure_ascii=False)
#sqsと接続
try:
sqs = boto3.client('sqs',
aws_access_key_id=os.environ["YOUR_ACCESS_KEY_ID"],
aws_secret_access_key=os.environ["YOUR_SECRET_ACCESS_KEY"],
region_name='ap-northeast-1'
)
# メッセージをSQSに送信
response = sqs.send_message(
QueueUrl=os.environ['YOUE_QUEUE_NAME'],
MessageBody=message
)
logging.info(f'Successfully sent message: {response}')
except Exception as e:
logging.error(f'Failed to send message: {e}')
後続のlambdaで、SQSからメッセージを受け取るコードは以下になります!
def handler(event, context):
#SQSから要素を取得
queue_info = json.loads(event['Records'][0]['body'])
url = queue_info.get('url')
#ここから、取得したURLに対する後続の処理を記載
ソリューションの特徴
完全サーバーレス
EC2インスタンスなどを使用していないため、サーバーを管理する必要がありません。
処理が走っていない時に料金は発生せず、監視も不要なので、運用面で非常に楽に管理することができます。
コスト
lambdaは1ヶ月あたり、100万件分のリクエストが無料であり、その後も100万リクエストあたり0.2USDで使用可能です。
また、SQSも同様に毎月100万件まで無料で実施可能です。
その後の料金も100万-1億リクエストまでは、100万リクエストあたり0.4USDで使用できます。
このように、lambdaとSQSを用いたサーバーレスアーキテクチャは、非常にコストエフェクティブなソリューションの1つです!
lambdaの同時実行の特性
lambdaはデフォルトで1アカウントに対し、1リージョンで1000件まで同時実行することが可能です。
処理単位を細かくlambdaで分けることにより、素早く処理を完了することができます!
インターフェースの統一と転用
このようなアーキテクチャで処理を実施するにあたり、インターフェースを工夫しました。
SQSとlambda間でやり取りをするインターフェース項目を、json形式で設定するのですが、これらのキー値を全体的に統一しています。
SQSのjsonに載せるキー名を、SQSや内部のコードで統一し、SQSから受け取る際のコードを転用できるようにすることで、開発効率を向上させることができます!
また、URL以外から文章を取得する必要があるケースも、今後の拡張としてあったため、3の文章を要約する処理へのインターフェースを拡張しやすいように設計して開発したことにより、今後文章の取得元が増えても、コード修正不要で3と4のメソッドを使用することができます。
lambdaで処理を細かく分けることで、影響範囲の制限を簡略化することができます!
参考
lambda料金について: https://aws.amazon.com/jp/lambda/pricing/
lambdaの無料枠について: https://aws.amazon.com/jp/lambda/pricing/?loc=ft#Free_Tier
SQSの料金について: https://aws.amazon.com/jp/sqs/pricing/
lambdaの同時実行について: https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-concurrency.html