设置非常简单:
后端服务向 SQS 发送消息 -> SQS 触发 lambda -> 执行 lambda 代码
我在后端服务将消息发送到SQS后立即添加了日志。
然后我使用 CloudWatch 查看了 lambda 的日志。
令我惊讶的是,后端服务日志和第一个 lambda 日志之间有大约 10 秒的差距,这意味着 SQS 花了大约 10 秒来接收、处理并再次发送消息。
问题
SQS 处理传入消息需要 10 秒左右,这正常吗? 如果是的话,可以做得更快吗?
更新
多亏了评论,我才能够进一步了解这一点。在我的例子中,我们使用 TypeScript CDK,并使用以下
SqsEventSource
创建 lambda:
import eventSources = require("@aws-cdk/aws-lambda-event-sources")
const eventSource = new eventSources.SqsEventSource(
sqs.Queue.fromQueueAttributes(scope, "SomeId", {
queueArn: "someArn",
queueName: "someQueueName",
}),
{
batchSize: 100,
maxBatchingWindow: cdk.Duration.seconds(5),
},
)
据我了解
batchSize: 100
和maxBatchingWindow: cdk.Duration.seconds(5)
本质上意味着:“如果有 100 个事件或最迟在 5 秒后立即执行 lambda”。
所以 10 秒仍然比 5 秒太多(有时甚至需要 15-20 秒)。
这是一个错误吗?
更新2
为了使漏洞过程更易于测试,我决定通过 CLI 直接将消息发送到队列(因此后端服务不再与这里相关):
aws sqs --endpoint <endpoint> send-message --queue-url <queue-url> --message-body '{"test":"test1"}'
我连续执行了上述命令10次(全部执行最多花费了7秒),然后在CloudWatch中检查了lambda日志:
(我可以使用应用程序日志检查每个请求处理了多少消息,此处不可见)
正如你所看到的,第一次和第二次 lambda 执行之间有 16 秒的差距(其余看起来都很好)。由于我在最多 10 条 SQS 消息内发送了全部 10 条 SQS 消息。 7秒,这应该是不可能的。最大应有 5 秒或更差 10 秒的间隙。
这可能是什么原因?这是一个错误吗?
旁注:
我实际上遇到了这个问题,因为我的应用程序的系统测试失败了,因为它太慢了。对于系统测试,大约 50% 的情况下速度很慢,而另外 50% 的情况下则按预期工作。
我终于可以为我找出问题所在,尽管我无法确定为什么存在我的问题中所示的 16s diff。
一般问题是,如果您使用一批 SQS 消息执行 lambda 函数,并且其中一条消息无法处理(-> lambda 引发错误),则所有 SQS 消息都会在延迟几秒钟的情况下再次重试。
因此,如果同一批次中有有效的 SQS 消息与无效/失败的消息,则可能根本不会被处理,因为失败的消息会先被处理。这种情况可能会连续发生多次,在我的例子中导致延迟超过 1 分钟。
不幸的是,无法告诉 AWS 一批消息中只有少数消息有效,而其他消息则无效。如果 lambda 抛出错误,则始终重试批次中的所有消息。
有一些解决方法,实际上我选择用
try/catch
围绕每个 SQS 消息的处理,并且仅在处理所有消息后并且其中一条消息之前失败时才抛出错误。这仍然意味着会重试成功的消息,但至少会及时处理它们(请注意,对于此方法,您的 lambda 需要具有幂等性)。我根本不会建议这个解决方法,它只是一个带有待办事项评论的修补程序:)
我最近遇到了同样的问题(batchSize 和 maxBatchingWindow 意外延迟了 10 秒以上),因此对于遇到此问题并且无法理解为什么会发生这种情况的任何人,以下是 AWS 文档的说明:
如果您使用批处理窗口并且 SQS 队列包含的流量非常低,则 Lambda 可能会等待最多 20 秒,然后再调用您的函数。即使您将批处理窗口设置为低于 20 秒也是如此。
来源 1:https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html