AWS SQS FIFO + Lambda による Prepare-Challenge パターン実装ガイド
1. 概要
非同期処理を確実に完了させるPrepare-Challengeパターンを、AWS SQS FIFO(First-In-First-Out)キューとLambdaを使って実装するためのガイドです。
1.1 パターンの目的
- 外部システムとの非同期処理を確実に完了
- 処理の順序性を保証
- システム負荷の制御
- 処理状態の追跡容易性
1.2 AWS サービスの選定理由
-
SQS FIFO
- メッセージの厳密な順序保証
- 重複排除機能
- メッセージグループによる並列処理の制御
- デッドレターキュー(DLQ)によるエラー処理
-
Lambda
- サーバーレスでの柔軟なスケーリング
- SQSとの統合が容易
- コスト効率の良い実行環境
- 監視・ログ収集の容易さ
2. キュー設計パターン
2.1 優先度別キューの構成
高優先度キュー
const highPriorityQueue = new sqs.Queue(this, 'HighPriorityQueue', {
fifo: true,
contentBasedDeduplication: true,
retentionPeriod: Duration.minutes(15),
visibilityTimeout: Duration.seconds(30)
});
- 即時処理が必要な重要な業務処理用
- 短い保持期間と可視性タイムアウト
- 1メッセージずつの即時処理
標準優先度キュー
const standardPriorityQueue = new sqs.Queue(this, 'StandardPriorityQueue', {
fifo: true,
contentBasedDeduplication: true,
retentionPeriod: Duration.hours(1),
visibilityTimeout: Duration.seconds(30)
});
- 通常の業務処理用
- 適度な保持期間
- バッチサイズによる効率的な処理
低優先度キュー
const lowPriorityQueue = new sqs.Queue(this, 'LowPriorityQueue', {
fifo: true,
contentBasedDeduplication: true,
retentionPeriod: Duration.hours(2),
visibilityTimeout: Duration.seconds(60)
});
- バッチ処理など、時間的余裕のある処理用
- 長めの保持期間と可視性タイムアウト
- 大きめのバッチサイズでの処理
2.2 共通の設定ポイント
-
コンテンツベースの重複排除
contentBasedDeduplication: true
- メッセージ本体に基づく自動的な重複排除
- 5分間の重複排除ウィンドウ
-
デッドレターキュー(DLQ)
deadLetterQueue: { queue: dlqQueue, maxReceiveCount: 3 }
- 失敗メッセージの分離
- 再処理ポリシーの設定
- 長期の保持期間設定
-
メッセージグループID
- 同一処理グループ内での順序保証
- 業務単位での並列処理制御
3. Lambda Trigger設定
3.1 基本設定
const eventSource = new lambdaEventSources.SqsEventSource(queue, {
batchSize: 10,
maxBatchingWindow: Duration.seconds(5),
reportBatchItemFailures: true
});
3.2 優先度別の設定例
高優先度キューのトリガー
{
batchSize: 1,
maxBatchingWindow: Duration.seconds(0),
reportBatchItemFailures: true
}
標準優先度キューのトリガー
{
batchSize: 5,
maxBatchingWindow: Duration.seconds(5),
reportBatchItemFailures: true
}
低優先度キューのトリガー
{
batchSize: 10,
maxBatchingWindow: Duration.seconds(10),
reportBatchItemFailures: true
}
4. メッセージ送信パターン
4.1 基本的なメッセージ構造
interface PrepareChallengeMessage {
processType: string;
priority: 'HIGH' | 'STANDARD' | 'LOW';
requestId: string;
timestamp: string;
payload: {
[key: string]: any;
};
metadata?: {
retryCount?: number;
originalTimestamp?: string;
};
}
4.2 送信パラメーター例
const sendParams = {
QueueUrl: queueUrl,
MessageBody: JSON.stringify(message),
MessageGroupId: groupId,
MessageDeduplicationId: deduplicationId
};
4.3 メッセージグループIDの設定パターン
-
注文処理の場合
MessageGroupId: `ORDER_${orderId}`
- 同一注文の順序性保証
-
顧客単位の処理の場合
MessageGroupId: `CUSTOMER_${customerId}`
- 同一顧客の処理順序保証
-
バッチ処理の場合
MessageGroupId: `BATCH_${batchType}`
- 同種バッチの順序性保証
5. エラーハンドリング
5.1 Lambda側の実装
export const handler = async (event: SQSEvent) => {
const batchItemFailures: { itemIdentifier: string }[] = [];
for (const record of event.Records) {
try {
const success = await processMessage(record);
if (!success) {
batchItemFailures.push({
itemIdentifier: record.messageId
});
}
} catch (error) {
batchItemFailures.push({
itemIdentifier: record.messageId
});
}
}
return { batchItemFailures };
};
5.2 再処理戦略
-
Prepare Phase失敗時
- 同一キューの後方に再エンキュー
- バックオフ時間の設定
- 最大再試行回数の管理
-
Challenge Phase失敗時
- DLQへの移動
- アラート通知
- 手動再処理の検討
6. モニタリングと運用
6.1 CloudWatchメトリクス
- キューの深さ
- 処理遅延時間
- エラー率
- DLQメッセージ数
6.2 アラート設定
new cloudwatch.Alarm(this, 'DLQAlarm', {
metric: dlqQueue.metricApproximateNumberOfMessagesVisible(),
threshold: 1,
evaluationPeriods: 1,
alarmDescription: 'Messages in DLQ detected'
});
6.3 運用上の注意点
-
キャパシティ管理
- FIFOキューの制限(1秒あたり300メッセージ)
- Lambda同時実行数の制限
- メモリ使用量の監視
-
コスト最適化
- バッチサイズの適切な設定
- Lambda実行時間の最適化
- 保持期間の適切な設定
-
メンテナンス性
- ログレベルの適切な設定
- エラーメッセージの明確化
- デバッグ情報の充実
7. ベストプラクティス
-
設計原則
- 単一責任の原則を守る
- 疎結合な設計を心がける
- 監視可能性を確保する
-
実装のポイント
- メッセージの冪等性確保
- タイムアウト値の適切な設定
- エラーハンドリングの徹底
-
運用面での推奨事項
- 定期的なDLQの確認
- パフォーマンスメトリクスの監視
- キャパシティプランニングの実施