backend
A
信頼度ランク
| S | 公式ソース確認済み |
| A | 成功実績多数・失敗例少数 |
| B | 賛否両論 |
| C | 動作未確認・セキュリティリスク高 |
| Z | 個人所感 |
SQSポーリング — ロングポーリング vs ショートポーリングとコスト最適化
SQSのショートポーリングとロングポーリングの違い、WaitTimeSecondsの設定、ReceiveMessageWaitTimeSecondsによるキュー設定、Lambdaとの統合時のポーリング動作、コスト削減効果を解説。
一言結論
SQSはロングポーリング(WaitTimeSeconds=20)を設定するだけで空ポーリングを95%削減できるため常に有効化すべきで、LambdaトリガーとしてSQSを使う場合はAWS側が自動でロングポーリングを実施するためアプリ側での実装は不要だ。
ショートポーリング vs ロングポーリング
ショートポーリング(デフォルト):
→ SQSは即座にレスポンスを返す
→ メッセージがなければ空レスポンス
→ 毎回APIリクエストが発生 → コスト高
→ WaitTimeSeconds = 0
ロングポーリング(推奨):
→ SQSはメッセージが来るまで最大20秒待つ
→ メッセージがなければ20秒後に空レスポンス
→ APIリクエスト数を大幅削減 → コスト低
→ WaitTimeSeconds = 1〜20
ロングポーリングの設定方法
# キューのデフォルトをロングポーリングに設定
aws sqs set-queue-attributes \
--queue-url https://sqs.ap-northeast-1.amazonaws.com/123456789012/my-queue \
--attributes '{"ReceiveMessageWaitTimeSeconds": "20"}'
# または個別のReceiveMessageリクエストで指定
aws sqs receive-message \
--queue-url https://sqs.ap-northeast-1.amazonaws.com/123456789012/my-queue \
--max-number-of-messages 10 \
--wait-time-seconds 20
コスト削減効果
例: メッセージ頻度 10メッセージ/分のキュー、1秒ごとのポーリング
ショートポーリング(1秒間隔):
1分間のAPIリクエスト: 60回
1ヶ月: 60 × 60 × 24 × 30 = 2,592,000 リクエスト
料金: 約$1.04/月(最初の100万件は無料)
ロングポーリング(20秒待機):
1分間のAPIリクエスト: 3回(20秒に1回 = 3回)
1ヶ月: 3 × 60 × 24 × 30 = 129,600 リクエスト
料金: 無料(100万件以内)
→ ロングポーリングで95%のAPIリクエスト削減
→ 誤検知(空レスポンス)も95%削減
Python でのロングポーリング実装
import boto3
import time
sqs = boto3.client('sqs')
QUEUE_URL = 'https://sqs.ap-northeast-1.amazonaws.com/123456789012/my-queue'
def poll_messages():
"""ロングポーリングでメッセージを継続処理"""
while True:
response = sqs.receive_message(
QueueUrl=QUEUE_URL,
MaxNumberOfMessages=10, # 最大10件
WaitTimeSeconds=20, # 最大20秒待機
VisibilityTimeout=120 # 処理中の再可視化防止
)
messages = response.get('Messages', [])
if not messages:
# 20秒間メッセージなし → 再度ポーリング
continue
for message in messages:
try:
process_message(message)
# 処理成功後に削除
sqs.delete_message(
QueueUrl=QUEUE_URL,
ReceiptHandle=message['ReceiptHandle']
)
except Exception as e:
print(f"Error processing message: {e}")
# 削除しなければVisibilityTimeout後に再処理
def process_message(message):
import json
body = json.loads(message['Body'])
print(f"Processing: {body}")
# 実際の処理ロジック
Lambda + SQS のポーリング動作
Lambdaがトリガーとして設定された場合:
→ Lambda サービス(AWS側)が自動的にロングポーリングを実施
→ ユーザーコードでポーリングを実装する必要なし
→ バッチサイズに応じてメッセージを取得してLambdaに渡す
Lambda + SQS の設定:
BatchSize: 1〜10,000(FIFOは最大10)
MaximumBatchingWindowInSeconds: メッセージを集めてバッチ化する待機時間(0〜300秒)
# SQS を Lambda のトリガーとして設定
aws lambda create-event-source-mapping \
--event-source-arn arn:aws:sqs:ap-northeast-1:123456789012:my-queue \
--function-name my-function \
--batch-size 10 \
--maximum-batching-window-in-seconds 5 # 5秒間バッチを集める
FIFO キューでの注意点
FIFO キューの特性:
→ MessageGroupId ごとに順序が保証
→ ロングポーリングは FIFO キューでも使用可能
FIFO キューの制限:
→ スループット: デフォルト300 TPS(スループット高速化を有効にすると3,000 TPS)
→ バッチサイズ: 最大10メッセージ
→ DeduplicationId: 重複排除ID(5分間有効)
バッチウィンドウの効果
MaximumBatchingWindowInSeconds(バッチウィンドウ):
0秒(デフォルト):
→ メッセージが1件でも来たらすぐにLambdaを起動
→ 低レイテンシー、コスト高め
5秒:
→ 5秒間またはBatchSize個メッセージが溜まるまで待機
→ 一度に多くのメッセージをバッチ処理
→ Lambda起動回数削減 → コスト削減
使い所:
リアルタイム処理が必要: 0秒
バッチ処理可能・コスト削減: 5〜300秒
試験頻出ポイント
| シナリオ | 回答 |
|---|---|
| SQSの空ポーリングを削減 | ロングポーリング(WaitTimeSeconds: 1〜20) |
| Lambdaのポーリング実装 | Lambda側が自動でロングポーリング |
| SQSのコスト最適化 | ロングポーリング + バッチウィンドウ |
| FIFO キューの最大TPS(デフォルト) | 300 TPS(高速化で3,000 TPS) |
| バッチウィンドウ最大値 | 300秒(5分) |
まとめ
SQSロングポーリングはWaitTimeSecondsを設定するだけで空ポーリングによるAPIリクエスト数を大幅に削減できる。LambdaとSQSの組み合わせではAWS側が自動的にロングポーリングを実施するため実装不要。バッチウィンドウでさらにLambda起動回数を削減できる。