问题描述
public async Task FunctionHandler(SQSEvent evnt,ILambdaContext context)
{
foreach (var message in @event.Records)
{
// Do work
// If a message processed successfully delete the SQS message
// If a message Failed to process throw an exception
}
}
令人困惑的是,虽然我不处理在我的数据库中创建记录的验证逻辑(已经存在),但我看到具有相同 ID 的数据库记录创建了两次,这意味着同一条消息处理了不止一次!
在我的代码中,我在成功处理后删除消息或在失败时抛出异常假设所有剩余的有序消息将返回到任何消费者可见的队列进行重新处理,但我现在可以看到代码失败,因为相同的记录为成功的事件创建两次。
AWS SQS FIFO 是一次性交付还是我缺少某种重试处理策略?
这是我在成功处理后删除消息的方式。
var deleteMessageRequest = new DeleteMessageRequest
{
QueueUrl = _sqsQueueUrl,ReceiptHandle = message.ReceiptHandle
};
var deleteMessageResponse =
await _amazonSqsClient.DeleteMessageAsync(deleteMessageRequest,cancellationToken);
if (deleteMessageResponse.HttpStatusCode != HttpStatusCode.OK)
{
throw new AggregateSqsProgramEntryPointException(
$"Amazon SQS DELETE ERROR: {deleteMessageResponse.HttpStatusCode}\r\nQueueURL: {_sqsQueueUrl}\r\nReceiptHandle: {message.ReceiptHandle}");
}
文档对此非常明确
"FIFO 队列提供恰好一次的处理,这意味着每个 消息被传递一次并保持可用直到消费者 处理它并删除它。”
他们还提到保护您的代码免于重试,但这对于仅一次传递队列类型来说令人困惑,但我在他们的文档中看到以下内容令人困惑。
恰好一次处理。 与标准队列不同,FIFO 队列没有 引入重复消息。 FIFO 队列可帮助您避免发送 复制到队列中。如果您在 5 分钟的重复数据删除间隔,Amazon SQS 不会引入任何 重复进入队列。
消费者重试(这怎么可能)?
如果消费者检测到失败的 ReceiveMessage 操作,它可以重试 根据需要多次使用相同的接收请求尝试 ID。 假设消费者至少收到一个确认 在可见性超时到期之前,多次重试不会影响 消息的排序。
解决方法
这完全是我们的应用程序错误以及由于非线程安全支持我们如何处理 Eventssourcing 聚合端点。