Lambda新機能 Amazon SQSイベントソースによる同時呼び出しの最大数制御を試してみました

この記事は公開されてから半年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「AWS Lambda がイベントソースとして Amazon SQS の最大同時実行数をサポート」 との事でしたので
これまでのLambda同時実行数を設定する方法と、どのような違いがあるのかを検証してみました。

https://aws.amazon.com/jp/about-aws/whats-new/2023/01/aws-lambda-maximum-concurrency-amazon-sqs-event-source/

目次

新機能の概要

SQSイベントソースのLmabda同時実行数制御は、これまではLambdaの [同時実行設定] から、予約された同時実行の設定のみだったが、本UpdateにてLambdaの [トリガー設定] から、最大同時実行数を設定可能となった。

設定方法の違いによる変化

SQSトリガー設定の最大同時実行数設定では、Lambda関数実行数を一定にしつつ、Throttleが抑制された事を確認できた。
DLQを利用する場合、Throttleが発生すると配信されたメッセージの受信回数カウントがカウントアップされ、正常なメッセージでもDLQ移動が発生する可能性があるため、有用性を感じた。

(元々の機能)Lambdaの予約された同時実行数の上限設定

条件

  • 1,000メッセージをキューイング
  • Lambda設定
    • 予約された同時実行 5
  • SQSトリガー設定
    • バッチサイズ: 5
    • 最大同時実行数: 設定無し

Lambda Metrics

Throttleが発生する。

(新機能)SQSトリガー設定の最大同時実行数設定

条件

  • 1,000メッセージをキューイング
  • Lambda設定
    • 予約された同時実行 設定無し
  • SQSトリガー設定
    • バッチサイズ: 5
    • 最大同時実行数: 5

Lambda Metrics

Throttleは発生しない。

多めのメッセージを捌く時間変化

冒頭のリンク先にある下記記載が気になったので確かめてみた。

関数が使用する同時実行の数は制限できましたが、関数のスロットリングによりスループットの一貫性が低下し、メッセージの再試行を余儀なくされていました

10,000メッセージをキューイングし、処理時間を確認した。
トータルの処理時間としては、(スロットリングは大量に発生しているが)元々の機能の方が多少速かった。

後日、8万件程のメッセージキューイングにて、処理完了時間を計測したところ、元々の機能の方が15%ほど早く処理を終えたので、大量のキューを処理するシステムにて、これまでの設定から変更する際にはテストが必要と感じた。
(Lambdaの予約された同時実行数上限設定: 39分 vs SQSトリガー設定の最大同時実行数設定: 48分)

メッセージ処理の再試行という観点では、スロットリングが発生しない分、常に大量のデータが処理され続ける環境下において安定した処理(DLQにメッセージが落ちる事も無い)が行えるものと考えた。

(元々の機能)Lambda同時実行設定

SQS Metrics

Lambda Metrics

(新機能)SQSトリガー設定の最大同時実行数設定

SQS Metrics

Lambda Metrics

テストプログラム

下記のような簡易的なプログラムで確認を実施しました。

SQSキューイング

import boto3
import json
import datetime
from zoneinfo import ZoneInfo

sqs = boto3.client('sqs')
url = 'https://sqs.ap-northeast-1.amazonaws.com/[AWSAccountID]/[sqs-name]'

for num in range(1000):
    body = {
        "Num": num+1,
        "time": str(datetime.datetime.now(ZoneInfo("Asia/Tokyo")))
    }

    response = sqs.send_message(
        QueueUrl=url,
        DelaySeconds=0,
        MessageBody=(
            json.dumps(body)
        )
    )
    
    if (num % 100 == 0):
        print ("Queued %s messages." % num)

Lambda

import json
import time

def lambda_handler(event, context):
    
    for record in event['Records']:
        payload = record["body"]
        time.sleep(0.1)
        print(str(payload))

まとめ

SQS-Lambda構成(特にDLQ利用)においてとても有用なUpdateと感じました。
個人的にはダッシュボードを眺めるときに、Lambda関数のThrottlesでヒヤッとしなくて良いのは精神的にも良いかなと思いました。

一方でSQS-Lambda構成にて常時発生するポーリングについて何らかUpdateがあると嬉しいと思うこの頃です。
(数が多くなければ費用的には大したことありませんが)

投稿者プロフィール

takashi
Japan AWS Ambassadors 2023, 2024
開発会社での ASP型WEBサービス企画 / 開発 / サーバ運用 を経て
2010年よりスカイアーチネットワークスに在籍しております

機械化/効率化/システム構築を軸に人に喜んで頂ける物作りが大好きです。

ABOUTこの記事をかいた人

Japan AWS Ambassadors 2023, 2024 開発会社での ASP型WEBサービス企画 / 開発 / サーバ運用 を経て 2010年よりスカイアーチネットワークスに在籍しております 機械化/効率化/システム構築を軸に人に喜んで頂ける物作りが大好きです。