📝

Lambda と SQS でイベントソースマッピングを使用しない方法を試してみた

に公開

Amazon SQS での Lambda の使用 - AWS Lambda
Lambda と SQS でイベントソースマッピングを使用すると以下のようなメリットがあります。

  • Lambda がキューを自動的にポーリング
  • Lambda がメッセージを正常に受信すると Lambda が自動的にキューからメッセージを削除

イベントソースマッピングを使用しない場合、ポーリングやメッセージの受信、削除処理を明示的に実装する必要があります。
Amazon SQS でのメッセージの受信と削除 - Amazon Simple Queue Service

処理後、メッセージを完全に削除するには、明示的に削除リクエストを送信する必要があります。

SQS + Lambda という⾮同期処理 ⻩⾦パターン再⼊⾨ #AWSDevDay / SQS-Lambda-DevDay2022 - Speaker Deck

今回はあえてイベントソースマッピングを使用しない方法を試してみました。

実装内容

Lambda 側で以下の処理を実装しました。

Lambda の設定は以下の通りです。

  • ランタイム: Python 3.13
  • 実行ロール: AdministratorAccess アクセス権限を付与
  • コード: 以下の通り
import json
import boto3

def lambda_handler(event, context):
    sqs = boto3.client('sqs')
    queue_url = 'your-queue-url'
    
    try:
        response = sqs.receive_message(
            QueueUrl=queue_url,
            WaitTimeSeconds=5
        )
        
        if 'Messages' in response:
            messages = response['Messages']

            for message in messages:
                print(f"メッセージ内容: {message['Body']}")

                sqs.delete_message(
                    QueueUrl=queue_url,
                    ReceiptHandle=message['ReceiptHandle']
                )
                print(f"メッセージを削除しました")
            
            return {
                'statusCode': 200,
                'body': json.dumps(f'{len(messages)}件のメッセージを処理しました')
            }
        else:
            print("メッセージはありませんでした")
            return {
                'statusCode': 200,
                'body': json.dumps('処理するメッセージがありませんでした')
            }
            
    except Exception as e:
        print(f"エラーが発生しました: {str(e)}")
        return {
            'statusCode': 500,
            'body': json.dumps(f'エラー: {str(e)}')
        }

動作確認

動作確認のためにデフォルト設定で SQS の通常キューを作成しました。
SQS コンソールのメッセージを送受信から適当なメッセージを送信します。

イベントソースマッピングを設定した場合はメッセージの投入後に自動的に Lambda がメッセージを取得しますが、今回は自動での取得は行われません。
そのため、SQS キュー側の利用可能なメッセージは 1 のままとなります。

このタイミングで Lambda をコンソールからテスト実行します。

以下のようなログが出力されればメッセージの処理に成功しています。

メッセージ内容: This is test
メッセージを削除しました

再度 SQS コンソールを確認すると、利用可能なメッセージが 0 になったことを確認できます。

これは Lambda から明示的にメッセージの削除処理を実施したためです。
つまり、以下の流れで処理が行われたことになります。

  1. SQS キューにメッセージを送信
  2. Lambda から ReceiveMessage API でメッセージを取得
  3. Lambda から DeleteMessage API でメッセージを削除
  4. SQS キューからメッセージが削除される

ポーリングについて

イベントソースマッピングでは Lambda から SQS キューへのポーリングも自動的に行われます。
一方、上記の実装ではポーリングの仕組みを実装していません。

ポーリングを実装する方法としては EventBridge ルールから定期的に Lambda を呼び出す方法が考えられます。
スケジュールに従って Lambda 関数を呼び出す - AWS Lambda

イベントソースマッピングではどの程度の間隔でポーリングが実装されているかは不明なため、独自にポーリングの仕組みを実装する場合には間隔に注意する必要があります。

例えば、1 時間おきの実行ではリアルタイム性が損なわれるためより、リアルタイム性を重視する場合にはより短い間隔での実行が必要になります。
一方で、頻繁にキューにメッセージを送信しない場合には ReceiveMessage API を実行しても空のレスポンスが返る頻度が多くなる可能性があり、Lambda コストパフォーマンスが低下します。

独自にポーリングの仕組みを実装する場合、何を重視するかによってポーリング間隔を判断する必要がありそうです。

まとめ

今回は Lambda と SQS でイベントソースマッピングを使用しない方法を試してみました。
どなたかの参考になれば幸いです。

参考資料

Discussion