简体   繁体   English

按 SQS 消息数触发 Lambda

[英]Trigger Lambda by number of SQS messages

I have a SQS which will receive a huge number of messages.我有一个 SQS,它将接收大量消息。 The messages keep coming to the queue.消息不断进入队列。

And I have a use case where if the number of messages in a queue reaches X number (such as 1,000), the system needs to trigger an event to process 1,000 at a time.我有一个用例,如果队列中的消息数量达到 X 个(例如 1,000),系统需要触发一个事件来一次处理 1,000 个。

And the system will make a chunk of triggers.系统会触发一大堆触发器。 Each trigger has a thousand messages.每个触发器都有一千条消息。

For example, if we have 2300 messages in a queue, we expect 3 triggers to a lambda function, the first 2 triggers corresponding to 1,000 messages, and the last one will contain 300 messages.例如,如果我们有 2300 条消息在队列中,我们期望 3 个触发器到 lambda 函数,前 2 个触发器对应于 1,000 条消息,最后一个将包含 300 条消息。

I'm researching and see CloudWatch Alarm can hook up to SQS metric on "NumberOfMessageReceived" to send to SNS.我正在研究并看到 CloudWatch 警报可以连接到“NumberOfMessageReceived”上的 SQS 指标以发送到 SNS。 But I don't know how can I configure a chunk of alarms for each 1,000 messages.但我不知道如何为每 1,000 条消息配置一大块警报。

Please advice me if AWS can support this use case or any customize we can make to achieve this.如果 AWS 可以支持此用例或我们可以为实现此目的进行的任何定制,请告知我。

在此处输入图像描述

So after going through some clarifications on the comments section with the OP, here's my answer (combined with @ChrisPollard's comment):因此,在与 OP 对评论部分进行了一些澄清之后,这是我的答案(结合@ChrisPollard 的评论):

Achieving what you want with SQS is impossible, because every batch can only contain up to 10 messages.用 SQS 实现你想要的是不可能的,因为每个批次最多只能包含 10 条消息。 Since you need to process 1000 messages at once, this is definitely a no-go.由于您需要一次处理 1000 条消息,这绝对是不行的。

@ChrisPollard suggested to create a new record in DynamoDB every time a new file is pushed to S3. @ChrisPollard 建议每次将新文件推送到 S3 时在 DynamoDB 中创建一条新记录。 This is a very good approach.这是一个非常好的方法。 Increment the partition key by 1 every time and trigger a lambda through DynamoDB Streams .每次将分区键递增 1 并通过DynamoDB Streams触发 lambda。 On your function, run a check against your partition key and, if it equals 1000, you run a query against your DynamoDB table filtering the last 1000 updated items (you'll need a Global Secondary Index on your CreatedAt field).在您的函数上,对您的分区键运行检查,如果它等于 1000,则对您的 DynamoDB 表运行一个查询,过滤最后 1000 个更新的项目(您需要在 CreatedAt 字段上使用全局二级索引)。 Map these items (or use Projections ) to create a very minimal JSON that contains only the necessary information.映射这些项目(或使用Projections )以创建仅包含必要信息的极简 JSON。 Something like:就像是:

[
    {
     "key": "my-amazing-key",
     "bucket": "my-super-cool-bucket"
    },
    ...
]

A JSON like this is only 87 bytes long (if you take the square brackets out of the game because they won't be repeated, you're left out with 83 bytes).像这样的 JSON 只有 87 个字节长(如果你把方括号从游戏中去掉,因为它们不会重复,你就剩下 83 个字节了)。 If you round it up to 100 bytes, you can still successfully send it as one event to SQS, as it will only be around 100KB of data.如果将其四舍五入到 100 字节,您仍然可以成功地将其作为一个事件发送到 SQS,因为它只有大约 100KB 的数据。

Then have one Lambda function subscribe to your SQS queue and then finally concatenate the 1 thousand files.然后让一个 Lambda 函数订阅您的 SQS 队列,最后连接 1000 个文件。

Things to keep in mind:要记住的事情:

  1. Make sure you really create the createdAt field in DynamoDB.确保您确实在 DynamoDB 中创建了 createdAt 字段。 By the time it hits one thousand, new items could have been inserted, so this way you make sure you are reading the 1000 items that you expected.当它达到 1000 条时,可能已经插入了新项目,所以这样可以确保您正在阅读预期的 1000 条项目。

  2. On your Lambda check, just run batchId % 1000 = 0, this way you don't need to delete anything, saving DynamoDB operations.在您的 Lambda 检查中,只需运行 batchId % 1000 = 0,这样您就不需要删除任何内容,从而节省了 DynamoDB 操作。

  3. Watch out for the execution time of your Lambda.注意 Lambda 的执行时间。 Concatenating 1000 files at once may take a while to run, so I'd run a couple of tests and put 1 min overhead on top of it.一次连接 1000 个文件可能需要一段时间才能运行,所以我会运行几个测试并在其上放置 1 分钟的开销。 Ie, if it usually takes 5 mins, set your function's timeout to 6 mins.即,如果通常需要 5 分钟,请将函数的超时设置为 6 分钟。

If you have new info to share I am happy to edit my answer.如果您有新信息要分享,我很乐意编辑我的答案。

You can add alarms at 1k, 2k, 3k, etc...but that seems clunky.您可以在 1k、2k、3k 等处添加警报……但这似乎很笨拙。

Is there a reason you're letting the messages batch up?你让消息批量处理有什么原因吗? You can make this trigger event-based (when a queue message is added fire my lambda) and get rid of the complications of batching them.您可以使此触发器基于事件(当添加队列消息时触发我的 lambda)并摆脱批处理它们的复杂性。

I handled a very similar situation recently, process-A puts objects in an S3 bucket and every time it does it puts a message in the SQS, with the key and bucket details, I have a lambda which is triggered every hour, but it can be any trigger like your cloud watch alarm.我最近处理了一个非常类似的情况,进程-A 将对象放入 S3 存储桶中,每次它都会在 SQS 中放入一条消息,其中包含密钥和存储桶详细信息,我有一个每小时触发的 lambda,但它可以成为任何触发器,例如您的云手表警报。 Here is what you can do on every trigger:以下是您可以对每个触发器执行的操作:

  • Read the messages from the queue, SQS allows you to read only 10 messages at a time, and every time you read the messages, keep adding them to some list in your lambda, you also get a receipt handle for every message , you can use it to delete the messages and repeat this process until you read all 1000 messages in your queue.从队列中读取消息,SQS 允许您一次仅读取 10 条消息,并且每次读取消息时,不断将它们添加到 lambda 中的某个列表中,您还可以获得每条消息的收据句柄,您可以使用它删除消息并重复此过程,直到您阅读队列中的所有 1000 条消息。 Now you can perform whatever operations are required on your list and feed it to process B in a number of different ways , like a file in S3 and/or a new queue that process B can read from.现在,您可以执行列表上所需的任何操作,并以多种不同方式将其提供给进程 B,例如 S3 中的文件和/或进程 B 可以读取的新队列。

  • Alternate approach to reading messages: SQS allows you to read only 10 messages at a time, you can send an optional parameter 'VisibilityTimeout':60 that hides the messages from the queue for 60 seconds and you can recursively read all the messages until you dont see any messages in the queue, all while adding them to a list in lambda to process them, this can be tricky since you have to try out different values for visibility time out based on how long it takes to read 1000 messages.读取消息的替代方法:SQS 允许您一次仅读取 10 条消息,您可以发送可选参数 'VisibilityTimeout':60 将消息从队列中隐藏 60 秒,并且您可以递归读取所有消息,直到您不读取查看队列中的任何消息,同时将它们添加到 lambda 中的列表以处理它们,这可能很棘手,因为您必须根据读取 1000 条消息所需的时间尝试不同的可见性超时值。 Once you know you read all the messages, you can simply have the receipt handles and delete all of them.一旦您知道您阅读了所有消息,您就可以简单地拥有收据句柄并删除所有这些消息。 You can also purge the queue but , you may delete some of the messages that came in during this process that are not read at least once.您也可以清除队列,但是,您可能会删除在此过程中进入的一些至少未阅读一次的消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM