【问题标题】:AWS SQS Asynchronous Queuing Pattern (Request/Response)AWS SQS 异步排队模式(请求/响应)
【发布时间】:2017-11-23 03:40:01
【问题描述】:

我正在寻求有关我对产品做出的建筑设计决策的帮助。

我们有多个生产者(由 API 网关调用 Lambda 发起)将消息放入 SQS 队列(请求队列)。可以有多个同时调用,因此会有多个 Lambda 实例并行运行。

然后我们有消费者(假设是 20 个 EC2 实例)在 SQS 上进行长轮询以获取消息来处理它们。它们每个处理一条消息大约需要 30-45 秒。

理想情况下,我希望将响应发送回发出请求的生产者 - 这是我在使用 SQS 时遇到的问题。理论上我会有一个单独的响应队列,最初的 Lambda 生产者将使用它,但似乎没有办法挑选特定的相关响应。也就是说,每个 Lambda 函数都可能获取另一个函数的响应。我正在寻找类似于这种设计模式的东西:http://soapatterns.org/design_patterns/asynchronous_queuing

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

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

谢谢!

【问题讨论】:

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


    【解决方案1】:

    为每个请求创建一个(临时)响应队列

    聚会迟到了,但我想我可能会在我想要实现的目标上找到一些帮助,@MattHouser @Zaheer Ally,或者给解决相关问题的人一个想法。

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

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

    为了取回结果,生产者将创建一个临时响应队列,其名称标识符将嵌入发送给工作人员的消息中。因此,每个工人都会在这个临时队列上“发布”他的结果。

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

    【讨论】:

    • 成功了吗?恕我直言,这听起来像是一个很好的解决方案,我的意思是,如果您正在处理同步任务,这似乎是一种合理的处理方式。也可以尝试事先执行任务。就我而言,同步任务将是一些信息的排名,这就是为什么我倾向于使用 cronjob 对所有内容进行排名,从而消除触发该任务的 SQS 消息的必要性
    • 作为概念证明,它似乎工作得很好。不过,我没有机会在生产环境中对其进行测试,因为出于商业原因,我们决定不集成多个外部 API。对我们来说,像 cronjobs(或任何 pre-post-execution 方法)这样的解决方案是不可能的,因为我们依赖于实时数据,甚至缓存也需要谨慎执行。对于您的应用程序,cronjob 应该可以完成这项工作。您还可以考虑使用无服务器解决方案,例如使用您选择的触发器执行的 Lambda 函数(例如数据库 INSERT)
    • 这是要走的路,创建临时队列没有什么不好的地方。只需添加一种机制来清理和删除它们或重新使用它们。
    【解决方案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。

    【讨论】:

    • 嗨,马特,感谢您的回复。我不确定 S3 在这种情况下如何工作 - 生产者必须轮询以检查 S3 响应文件是否存在?我找不到在 S3 上的长轮询,所以即使我每秒检查一次,它似乎也相当低效,尤其是每分钟可能有数百个请求。
    • 正确,您必须轮询 S3。 AWS 无法向您的 Lambda 函数发回响应已准备就绪的信号。所以你有 4 个选项:(a) 使用 SQS,每个请求一个队列,(b) 使用 SQS,共享结果队列,(这些选项都不理想),(c) 轮询结果(S3、数据库等) .),或 (d) 使用非 AWS 服务。
    • 再次感谢,感谢您在此问题上的清晰和专业知识。我以前没有使用过 Redis,但是您的链接(尤其是请求 + 回复 MQ 模式)使它听起来像是一个不错的选择,所以我将对其进行调查,看看它是否适用于我们的环境。再次感谢。
    • 派对迟到了,但我想我可能会在我想要实现的目标上找到一些帮助,@Matt
    【解决方案3】:

    另一种选择是使用 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)。

    我刚刚偶然发现的另一件事是,通过 API Gateway 的请求当前为cannot take longer than 29 seconds,而这不能通过 AWS 增加。您提到您的工作需要 30 秒或更多秒,因此无论如何这对您使用 API Gateway 和 Lambda 来说可能是一个亮点。

    【讨论】:

      【解决方案4】:

      AWS 现在提供支持temporary queuesJava client。这对于请求/响应模式很有用。我看不到非 Java 版本。

      【讨论】:

        猜你喜欢
        • 2018-10-07
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        • 2021-01-04
        • 1970-01-01
        • 2016-07-25
        • 1970-01-01
        相关资源
        最近更新 更多