我目前正在使用SendGrid从许多无服务器的node.js Lambda函数发送电子邮件,并计划从SendGrid转移到SES(因为价格合理)。
SendGrid的速率限制非常高,以至于通过一些lambda函数并发地使用for循环向用户发送电子邮件从未引起问题。但是SES的速率限制较低(在我的情况下为每秒50封电子邮件),并且发生了最大发送速率限制超过错误。
如何在不超过速率限制的情况下尽可能快地发送电子邮件?
我目前的计划是通过多个lambda函数向SQS队列发送邮件请求,通过1个Lambda函数不定时运行接收SQS消息发送邮件,但我不知道如何控制向SES发送请求的速度。
6条答案
按热度按时间sycxhyv71#
我的结论
我决定创建两个SQS队列(A和B)。队列B用于触发电子邮件发送功能,队列A用于在等待队列中添加消息。因此我只需要控制消息从队列A移动到B的速度,这使得一切都变得简单。
我考虑了以下几点。
错误处理
一开始,我想用while-loops通过一个Lambda函数发送多封邮件,但这样会给错误处理带来困难,当超过速率限制错误或其他意外异常发生时,需要等待一段时间重试,但可能会超过Lambda函数的超时时间。
可扩展性
通过单个Lambda函数在1秒内从SQS队列接收50条消息并向SES发送50个请求是可能的,但是如果速率限制上升到300或500,则可能不可能在一秒内处理那么多请求。将消息从一个SQS队列移动到另一个SQS队列,以便为每个电子邮件调用Lambda函数,相对容易扩展。
邮件优先级
注册确认电子邮件与验证码需要立即发送,但活动电子邮件可以发送延迟。有两个SQS队列,我可以控制优先级。
AWS成本
为每封电子邮件调用一个Lambda函数比在一个Lambda函数中发送多封电子邮件需要更多的时间,但这方面的AWS成本并不是很昂贵。如果向SES发送请求需要1秒,则在128 MB内存(北弗吉尼亚州地区)下执行Lambda的成本为0.000002083美元。对于1000封电子邮件,这仅为0.02083美元,可以忽略。
q3aa05252#
您还可以使用Lambda Reserved Concurrency feature将并发Lambda执行的数量限制为50。并将SQS的批处理大小设置为1条消息。
在无服务器框架中,这看起来像:
这将确保您不会同时运行超过50个Lambda示例。
但是一个新的问题出现了-如果你的函数在〈1 s的时间内执行得太快,你最终会超过速率限制。
reservedConcurrency
如果你决定减少
reservedConcurrency
,假设你的代码在500 ms内运行。这意味着,如果你有50个并发的Lambda示例,它们将在前0.5s内发送50封电子邮件,然后在第二个0.5s内尝试发送50封电子邮件。然后将
reservedConcurrency
设置为25
。zwghvu4y3#
下面的方法保证当
arrayWithAllTheEmails
包含x或更多元素时,您将有x个并发调用。每次一个呼叫结束时,它都会调用下一个呼叫。
olhwl3o24#
你可以使用sleep()来实现这一点。
q7solyqu5#
溶液1
我认为你使用CloudWatch创建了一个预定事件,每隔1秒或2秒触发一次事件,它将调用lambda函数。在lambda函数内部,只从SQS中检索进程50条消息,并结束lambda函数。
溶液2
但我看到你把这个
running without stopping time
。如果您想这样做,那么您必须设置一个时间计数器,从开始向SES发送电子邮件请求到发送50个请求的时刻。
如果时间差大于1秒,则处理下一组电子邮件。
如果时间差小于1秒,则等待剩余时间,然后处理下一组电子邮件。
SES文档在此链接中讨论了相同的问题,并建议在代码中引入速率限制逻辑。
https://aws.amazon.com/blogs/messaging-and-targeting/how-to-handle-a-throttling-maximum-sending-rate-exceeded-error/
因为你是用node的所以你可以看看这个速率限制器库https://www.npmjs.com/package/ratelimiter
ctehm74n6#
2023年来这里的每个人:
Amazon在使用Amazon SQS作为事件源功能时引入了AWS Lambda函数的最大并发性,这似乎是此任务的一个很好的用例。source
下面是我们如何实现节流:https://github.com/michaelhaar/Heimdall-Burstable-SES