Amazon web services 对队列的工作人员进行速率限制(例如:SQS)

Amazon web services 对队列的工作人员进行速率限制(例如:SQS),amazon-web-services,aws-lambda,amazon-sqs,Amazon Web Services,Aws Lambda,Amazon Sqs,每天,我都会运行一个CRON任务,它会用大量需要完成的任务填充一个SQS队列。所以(例如)每天早上9点,空队列将收到大约100条需要处理的消息 我希望每秒钟都有一名新员工轮换,直到队列清空。如果任何任务失败,它将放在队列的后面重新运行 例如,如果每个任务最多需要1.5秒完成: 1秒后,1个工作进程将启动一条消息 2秒后,1名工作人员可能仍在运行消息A,1名工作人员将已开始运行消息B 100秒后,1名工作人员可能仍在运行消息XX,1名工作人员将拾取消息B,因为它在上一次失败 101秒后,直到第二

每天,我都会运行一个CRON任务,它会用大量需要完成的任务填充一个SQS队列。所以(例如)每天早上9点,空队列将收到大约100条需要处理的消息

我希望每秒钟都有一名新员工轮换,直到队列清空。如果任何任务失败,它将放在队列的后面重新运行

例如,如果每个任务最多需要1.5秒完成:

  • 1秒后,1个工作进程将启动一条消息
  • 2秒后,1名工作人员可能仍在运行消息A,1名工作人员将已开始运行消息B
  • 100秒后,1名工作人员可能仍在运行消息XX,1名工作人员将拾取消息B,因为它在上一次失败
  • 101秒后,直到第二天早上才传播更多的工作者

有没有办法在AWS lambda中配置这种类型的基础设施?

在我看来,您最好将消息发布到SNS,而不是SQS,然后让lambda函数订阅SNS主题

让Lambda担心它需要多少“实例”来响应负载

这里有一篇关于这种方法的博文,但谷歌可能会帮助你找到一个更接近你实际用例的方法


一种方法,尽管我不认为它是最佳的:

由CloudWatch事件触发的lambda(例如每秒或每10秒,取决于您的速率限制)。它轮询SQS以接收(最多)N条消息,然后将每条消息“扇出”到另一个Lambda函数


一些伪代码:

# Lambda 1 (schedule by CloudWatch Event / e.g. CRON)
def handle_cron(event, context):
    # in order to get more messages, we might have to receive several times (loop)
    for message in queue.receive_messages(MaxNumberOfMessages=10):
        # Note: the Event InvocationType so we don't want to wait for the response!
        lambda_client.invoke(FunctionName="foo", Payload=message.body, InvocationType='Event')


为什么不使用Lambda函数在早上9点开始轮询sqs,每次获取一条消息,并在每条消息之间休眠一秒钟?死信队列可以处理重试。在x秒后未收到来自SQS的消息后停止执行


这是一种独特的情况,您实际上不需要并行处理。

调用目前对我来说不是问题,问题在于速率限制。在这方面有什么建议吗?你能解释一下为什么你需要限制费率吗?这个答案可能会带来一个更好的答案。基本上,我们希望能够将消息发送到一个具有不合理速率限制的API,SNS不是即时的吗?如果您添加10万条消息,它将淹没lambda,如果您向SQS添加10万条消息,您可以以速率限制的速率(例如每分钟1000条)进行轮询。我想,但OP建议队列中包含约100条消息,而不是100000条消息。当你将负载乘以1000倍时,很多系统都会崩溃,而且为一个不可能发生的规模进行设计并不总是有意义的。这是一个有趣的用例。你能告诉我们为什么1秒的速率限制是必要的(即使是广义的)吗?它可以通过一个执行器来完成,该执行器每秒产生1个线程,并精确地处理1个SQS轮询,然后在不为空的情况下处理一个失败的队列——但我仍然很好奇它应该在哪里。谢谢我们正在使用它与第三方API进行通信,后者将我们对其服务的使用限制为每秒最多1个请求。我有相同的使用案例:对讲机速率限制为每10秒83个请求。系统的cron启动了一个批处理作业,该批处理作业发送到一个SQS队列,一个工人最终向Intercom发出请求,我猜您也可能有N个Cloudwatch事件,所有这些事件都使用相同的cron。。。限制为N秒,当您说“停止执行”时,您的意思是关闭事件吗?我的意思是使用lambda函数轮询SQS队列。在收到消息后,它应该处理它,然后休眠一秒钟。然后轮询另一条消息。如果您轮询消息并且在x秒内没有收到任何消息,请暂停lambda函数的执行,直到下一个cron.+1。我真的很喜欢这个设计。这比在达到API限制时调整每条消息的可见性要好得多。
# Lambda 2 (triggered only by the invoke in Lambda 1)
def handle_message(event, context):
    # handle message
    pass