AWS SQS异步排队模式(请求/响应)

时间:2017-06-20 14:21:53

标签: amazon-web-services aws-lambda amazon-sqs

我正在寻找有关我正在使用产品制作的建筑设计决策的帮助。

我们有多个生产者(由API Gateway调用Lambda启动)将消息放在SQS队列(请求队列)上。可以有多个同时调用,因此会有多个并行运行的Lambda实例。

然后我们让消费者(比如二十个EC2实例)在SQS上长时间轮询消息来处理它们。每个处理一条消息大约需要30-45秒。

然后,我希望将响应发送回发出请求的制作人 - 这是我正在与SQS斗争的部分。理论上我会有一个单独的响应队列,最初的Lambda生产者会消耗,但似乎没有办法挑选特定的相关响应。也就是说,每个Lambda函数可能会获取另一个函数的响应。我正在寻找类似于这种设计模式的东西:http://soapatterns.org/design_patterns/asynchronous_queuing

我能看到的唯一选择是为每个Lambda API调用创建一个新的SQS响应队列,在消息中传入其ARN以供消费者使用,但我无法想象这是非常有效的 - 特别是每分钟可能有数百条消息?我错过了一些明显的东西吗

我认为唯一的另一种选择是建立一个更大的消息代理(例如RabbitMQ / ApacheMQ)环境,但是如果可能的话我想避免这种情况。

谢谢!

3 个答案:

答案 0 :(得分:2)

是的,您可以将RabbitMQ用于更多" rpc"队列模式。

但是如果您想留在AWS中,请尝试使用SQS之外的其他内容进行响应。

相反,您可以使用S3进行响应。当您的生产者将项目放入SQS时,在消息中包含响应的S3目的地。当您的消费者完成任务时,将响应放在所需的S3位置。

然后你可以检查S3的响应。

<强>更新

您可以使用Redis完成类似RPC的消息队列。

https://github.com/ServiceStack/ServiceStack/wiki/Messaging-and-redis

然后,您可以将AWS ElastiCache用于Redis群集。这将完全取代SQS的使用。

答案 1 :(得分:2)

另一种选择是使用Redis的pub/sub机制来异步通知你的lambda后端工作已经完成。您可以将AWS's Elasticache for Redis用于全AWS管理的解决方案。您的lambda函数将为每个请求生成一个UUID,使用它作为要订阅的通道名称,在SQS消息中传递它,然后后端工作人员将在完成工作时向该通道发布通知。

我遇到了同样的问题所以I tried it out,它确实有效。是否值得花费仅仅轮询S3是另一个问题。您必须将lambda函数配置为run inside your VPC,以便他们可以访问您的Redis。无论如何,我必须这样做,因为我希望工作人员(在我的情况下也是lambda函数)能够访问我的Elasticsearch和RDS。但是有一些注意事项:最重要的是,您需要使用具有NAT网关(或您自己的NAT实例)的私有子网,因此它可以访问Internet和AWS托管服务(包括SQS)。

aws diagram

我偶然发现的另一件事是,通过API网关的请求目前是cannot take longer than 29 seconds,这是AWS无法增加的。您提到您的工作需要30秒或更长时间,因此无论如何,这可能是您使用API​​ Gateway和Lambda的一个showstopper。

答案 2 :(得分:1)

为了参加晚会,但我想我可能会找到一些帮助,我可能会找到一些帮助,@ MehHouser @Zaheer Ally,或者向处理相关问题的人提出一个想法。

我正面临着类似的挑战。我有一个API,根据客户的要求,需要与多个外部API进行通信并收集(延迟)结果。

由于我的PHP API是同步的,因此它只能按顺序执行这些请求。所以,我想使用请求队列,生产者(API)将发送消息。然后,多个工作人员将使用这些消息,每个消息执行这些外部API调用之一。

要获得结果,生产者将创建一个临时响应队列,其名称标识符将嵌入发送给工作人员的消息中。因此,每个工人都会发布&#39;他在这个临时队列中的结果。

与此同时,生产者将继续轮询临时队列,直到他收到预期的消息数。最后,他将删除队列并将收集的结果发送回客户端。

虽然看起来是正确的,但我觉得这个解决方案根本不优雅,容易出现故障,而且对于用PHP实现的典型HTTP请求 - 响应周期来说效率肯定不高。

有什么想法吗?