SQS 需要大约 10 秒来处理传入消息是否正常,是否可以使其更快?
Is it normal that SQS takes around 10s to process an incoming message and can it be made faster?
设置非常简单:
- 一个后端服务(例如Java)
- 一个 lambda(例如 Java脚本)
- 一个 SQS
后端服务向SQS发送消息->SQS触发lambda->执行lambda代码
我在后端服务向SQS发送消息后立即添加了一条日志。
然后我使用 CloudWatch 查看了 lambda 的日志。
令我惊讶的是后端服务日志和第一个 lambda 日志之间有大约 10 秒的间隔,这意味着 SQS 花了大约 10 秒来接收、处理和再次发送消息。
问题
SQS 需要大约 10 秒来处理传入消息是否正常?
如果是,是否可以做得更快?
更新
多亏了评论,我才能够对此进行更多追踪。在我的例子中,我们使用 TypeScript CDK 并且 lambda 是使用以下 SqsEventSource
:
创建的
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”。
所以10s还是5s太多了(有时甚至需要15-20s)。
这是一个错误吗?
更新 2
为了使 hole 过程更易于测试,我决定通过 CLI 直接将消息发送到队列(因此后端服务不再与此处相关):
aws sqs --endpoint <endpoint> send-message --queue-url <queue-url> --message-body '{"test":"test1"}'
上面的命令我连续执行了10次(全部执行最多7秒),然后查看CloudWatch中的lambda日志:
(我可以通过应用程序日志检查每个请求处理了多少消息,此处不可见)
正如您所看到的,在第一次和第二次 lambda 执行之间有 16 秒的间隔(其余的看起来很好)。因为我在最大值内发送了所有 10 个 SQS 消息。 7秒,这应该是不可能的。应该有最大 5 秒或最差 10 秒的间隔。
这可能是什么原因?这是一个错误吗?
旁注:
我确实遇到了这个问题,因为我的应用程序的系统测试失败了,因为它太慢了。对于系统测试,它发生在 50% 的时间里它很慢,而另外 50% 的时间它按预期工作。
我终于可以为我找出问题所在,尽管我无法确定为什么我的问题中有 16 秒的差异。
普遍的问题是,如果您使用一批 SQS 消息执行 lambda 函数,并且无法处理其中一条消息(-> lambda 抛出错误),所有 SQS 消息都会延迟重试几秒钟。
因此,如果在与 invalid/failing 消息相同的批次中存在有效的 SQS 消息,则它可能根本不会被处理,因为首先处理失败的消息。这可能会连续发生多次,导致我的延迟超过 1 分钟。
遗憾的是,没有办法告诉 AWS 批处理中有几条消息有效而其他消息无效。如果 lambda 抛出错误,则始终重试批处理中的所有消息。
有一些 ,我实际上选择用 try/catch
包围每个 SQS 消息的处理,并且仅在所有消息都已处理并且其中一个之前失败时才抛出错误.这仍然意味着成功的消息会被重试,但至少它们会被及时处理(请注意,对于这种方法,您的 lambda 需要是幂等的)。我根本不会建议这个解决方法,它只是一个带有待办事项评论的修补程序:)
设置非常简单:
- 一个后端服务(例如Java)
- 一个 lambda(例如 Java脚本)
- 一个 SQS
后端服务向SQS发送消息->SQS触发lambda->执行lambda代码
我在后端服务向SQS发送消息后立即添加了一条日志。
然后我使用 CloudWatch 查看了 lambda 的日志。
令我惊讶的是后端服务日志和第一个 lambda 日志之间有大约 10 秒的间隔,这意味着 SQS 花了大约 10 秒来接收、处理和再次发送消息。
问题
SQS 需要大约 10 秒来处理传入消息是否正常? 如果是,是否可以做得更快?
更新
多亏了评论,我才能够对此进行更多追踪。在我的例子中,我们使用 TypeScript CDK 并且 lambda 是使用以下 SqsEventSource
:
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”。
所以10s还是5s太多了(有时甚至需要15-20s)。
这是一个错误吗?
更新 2
为了使 hole 过程更易于测试,我决定通过 CLI 直接将消息发送到队列(因此后端服务不再与此处相关):
aws sqs --endpoint <endpoint> send-message --queue-url <queue-url> --message-body '{"test":"test1"}'
上面的命令我连续执行了10次(全部执行最多7秒),然后查看CloudWatch中的lambda日志:
(我可以通过应用程序日志检查每个请求处理了多少消息,此处不可见)
正如您所看到的,在第一次和第二次 lambda 执行之间有 16 秒的间隔(其余的看起来很好)。因为我在最大值内发送了所有 10 个 SQS 消息。 7秒,这应该是不可能的。应该有最大 5 秒或最差 10 秒的间隔。
这可能是什么原因?这是一个错误吗?
旁注:
我确实遇到了这个问题,因为我的应用程序的系统测试失败了,因为它太慢了。对于系统测试,它发生在 50% 的时间里它很慢,而另外 50% 的时间它按预期工作。
我终于可以为我找出问题所在,尽管我无法确定为什么我的问题中有 16 秒的差异。
普遍的问题是,如果您使用一批 SQS 消息执行 lambda 函数,并且无法处理其中一条消息(-> lambda 抛出错误),所有 SQS 消息都会延迟重试几秒钟。
因此,如果在与 invalid/failing 消息相同的批次中存在有效的 SQS 消息,则它可能根本不会被处理,因为首先处理失败的消息。这可能会连续发生多次,导致我的延迟超过 1 分钟。
遗憾的是,没有办法告诉 AWS 批处理中有几条消息有效而其他消息无效。如果 lambda 抛出错误,则始终重试批处理中的所有消息。
有一些 try/catch
包围每个 SQS 消息的处理,并且仅在所有消息都已处理并且其中一个之前失败时才抛出错误.这仍然意味着成功的消息会被重试,但至少它们会被及时处理(请注意,对于这种方法,您的 lambda 需要是幂等的)。我根本不会建议这个解决方法,它只是一个带有待办事项评论的修补程序:)