AWS Lambda-队列的存储状态

时间:2019-02-21 12:29:10

标签: amazon-web-services amazon-s3 aws-lambda amazon-dynamodb state

我目前负责构建用于政府机构与公民之间通信的无服务器体系结构,并且主要组成部分是某种形式的队列,其中包含针对每种公民请求的某种形式的对象/指针,并按优先级排序。然后,政府工作人员可以处理可用的元素。由于Lambda是无状态的,因此我需要以某种方式将队列保存到外部。

为了保存状态,我收集到可以使用DynamoDB或S3存储桶,并使用事件触发器来调用相关的Lambda方法。有些人还建议使用参数存储来保存一些状态变量。尽管无法保证Lambda不会终止,但在全球范围内存储事物的可能性也在上升,这似乎不是一个好主意。

最后,我还阅读了一些有关SQS的信息,尽管我不知道它是否完全适用于这种情况。

以这种方式使用Lambda时,最佳实践/建议方法是什么?由于事件触发,我倾向于使用S3存储桶,而不是将DynamoDB用作我们的数据库。

3 个答案:

答案 0 :(得分:4)

  

还可以在全球范围内存储内容,尽管您不能保证Lambda不会终止,但这似乎不是一个好主意。

正确-这根本不可行。请注意,当您说“ Lambda”时,您实际上指的是容器内的进程……并且每当您的Lambda函数同时处理多个调用时,您就会保证不会在同一个容器中运行-因此“全局”变量仅对优化有用,而对状态不起作用。同一功能的任何两个并发调用都具有两个完全不同的全局环境。

暂时忘掉所有有关Lambda的信息-我并不是说不要使用Lambda;我是说您是否使用Lambda与下面编写的其余内容无关-我建议一般而言,并行/并行操作可能是许多开发人员倾向于忽略的最重要因素之一尝试设计您所描述的内容时。

如何从此工作“队列”中分配工作是非常重要的考虑因素。您不能只是“查找下一项”并将其显示给工作人员。

您必须有一种方法来完成所有这些事情:

  • 找到下一个似乎可用的项目
  • 验证它确实可用
  • 将其分配给特定工作人员
  • 将其标记为不可分配

不仅如此,而且您必须能够以原子方式做所有这些事情-作为一个逻辑动作-并且不能发生冲突。

单纯的实现存在将相同的工作项目分配给两个或更多人的风险,第一个分配几乎被同时发生的后续分配盲目和无声地覆盖。

DynamoDB允许conditional updates -仅在满足特定条件时才更新记录。这是解决方案需要适应的一项关键功能-例如,当且仅当当前未分配项目x时,才将工作项目x分配给用户y。 如果条件在更新发生时不成立,则条件更新将失败,并且不会进行任何更改

S3不支持条件更新,因为与DynamoDB不同,S3在大多数情况下仅在eventual-consistency model上运行。在S3中的对象被更新或删除之后,不能保证对S3的下一个请求将返回最新版本,或者S3将不返回最近被删除的项目。这不是S3的缺陷-它是一种优化-但这使S3不适合“工作队列”方面。

跳过这一考虑,您将拥有一个似乎可以正常运行的系统,并且在大多数时间都可以正常运行...但是在其他时候,它“神秘地”表现出错误。

当然,如果您的工作项带有随附的文档(扫描的图像,PDF等),将它们存储在S3中是完全正确的……但是S3是存储“状态”的错误工具。出于相同的原因,SSM参数存储是错误的工具-当两个动作都需要同时修改“状态”时,它们无法协同工作。

“事件触发器”当然很有用,但是根据您的描述,最值得注意的“事件”不是来自数据或工作项的创建,而是当工作人员说“我正在为我的下一个工作做好准备。”正是在这一点上-由网站/应用程序代码触发-当执行上述步骤以选择项目并将其分配给工作人员时。 (实际上,可以是浏览器→API网关→Lambda)。根据您的描述,可能不需要创建新的工作项来触发“事件”,或者如果有的话,它并不是事件中最重要的。

您将需要一个适当的数据库。 DynamoDB和RDS都是候选对象。

SQS提供的队列旨在分离应用程序的两个部分-当两个进程以不同的速度运行时,SQS用作缓冲区,从而允许X安全地存储需要完成的工作,然后继续执行某些操作否则,直到Y能够完成工作为止。 SQS队列是不透明的-您无法自省队列中的内容,您只需接收下一条消息并负责处理它。从表面上看,这似乎可以部分地描述您的需求,但这并不是该用例的完美匹配。队列的保留时间有限,一旦成功处理了一条消息,消息就完全消失了。

还请注意,SQS仅与启用FIFO队列功能的用例相匹配,这保证了完美的按顺序交付和精确的一次交付-由于性能优化的原因,标准SQS队列不保证完美的按需交付。 -订单传递,并且在某些条件下可能会将同一条消息多次传递给同一消费者或其他消费者。但是SQS FIFO队列功能与事件触发器不共存,后者需要标准队列。

因此SQS可能起作用,但是您需要一个权威的数据库来存储工作和业务流程的结果。

答案 1 :(得分:1)

如果您需要存储消息,那么SQS并不是最好的工具,因为您的Lambda函数将需要处理该消息并将其最终存储在某个地方,从而使SQS只不过是一个中介。

考虑到您可以将文件(消息)存储在S3存储桶中,然后让一个Lambda占用其事件,S3方法可立即提供您所需的内容。然后,您的Lambda会处理此事件,并且文件在S3上将保持安全无虞。

如果此消息最终需要多个使用者,则可以将S3事件发送给SNS,最后可以将N个Lambda函数订阅给定的SNS主题。

答案 2 :(得分:1)

您似乎在此阶段对基础结构过于担心,而对应用程序设计的担心却不够。它将成为无服务器的事实并不会改变应用程序的基本功能-它仍将向用户显示UI,用户仍将选择必须触发某些业务逻辑的选项,并且信息仍将被存储在数据库中。

您描述的队列仅仅是处于特定状态的邮件的数据存储。该应用程序将具有某种形式的业务逻辑,用于确定要处理的下一条消息,该逻辑可以基于创建时间戳记,优先级,位置,类别,用户(例如,响应速度更快的VIP用户),要求提供服务的工作人员的专业化。下一条消息等。这不是“队列”,而是针对所有“未解决”的消息执行的计算,以确定要分配的下一条消息。

如果您希望不使用服务器,那么后端肯定会使用Lambda和数据库(例如DynamoDB或Amazon RDS)。应用程序应将所有内容存储在数据库中,以便数据可用于应用程序的业务逻辑。因为实际上没有“队列”,所以不需要使用SQS,并且参数存储只是在应用程序组件之间共享参数的一种方式–并不意味着要用于核心数据存储。

首先确定应用程序功能,然后确定适当的体系结构以使其实现。