繁体   English   中英

持续监听 AWS SQS 消息的模式

[英]Pattern to continuously listen to AWS SQS messages

我有一个名为QueueService的简单类,其中包含一些包装来自适用于 Java 的 AWS SQS 开发工具包的方法的方法。 例如:

public ArrayList<Hashtable<String, String>> receiveMessages(String queueURL) {
        List<Message> messages = this.sqsClient.receiveMessage(queueURL).getMessages();

        ArrayList<Hashtable<String, String>> resultList = new ArrayList<Hashtable<String, String>>();
        for(Message message : messages) {
            Hashtable<String, String> resultItem = new Hashtable<String, String>();
            resultItem.put("MessageId", message.getMessageId());
            resultItem.put("ReceiptHandle", message.getReceiptHandle());
            resultItem.put("Body", message.getBody());
            resultList.add(resultItem);
        }
        return resultList;
    }

我还有另一个名为App的类,它有一个main并创建了QueueService的实例。

我正在寻找一种“模式”来让App中的main监听队列中的新消息。 现在我有一个while(true)循环,我在其中调用receiveMessages方法:

while(true) {
            messages = queueService.receiveMessages(queueURL); 
            for(Hashtable<String, String> message: messages) {
                String receiptHandle = message.get("ReceiptHandle");
                String messageBody = message.get("MessageBody");
                System.out.println(messageBody);
                queueService.deleteMessage(queueURL, receiptHandle);
            }
        }

这是正确的方法吗? 我应该在 SQS SDK 中使用异步消息接收方法吗?

据我所知,Amazon SQS 无法支持主动侦听器模型,在这种模型中,Amazon SQS 会将消息“推送”到您的侦听器,或者在有消息时调用您的消息侦听器。

因此,您将始终需要轮询消息。 轮询支持两种轮询机制 - 短轮询和长轮询。 每个都有自己的优点和缺点,但在大多数情况下,您通常最终会使用长轮询,尽管默认的是短轮询。 长轮询机制在网络流量方面肯定更高效,更具成本效益(因为亚马逊按请求数量向您收费),并且当您希望以时间敏感的方式处理您的消息时,它也是首选机制( ~= 尽快处理)。

长轮询和短轮询还有更多错综复杂的地方值得了解,在这里解释所有这些有点困难,但如果您愿意,可以通过以下博客阅读更多关于此的详细信息。 它也有一些代码示例,应该会有所帮助。

http://pragmaticnotes.com/2017/11/20/amazon-sqs-long-polling-versus-short-polling/

就 while(true) 循环而言,我会说这取决于。 如果您使用长轮询,您可以将等待时间设置为(最大)20 秒,这样如果没有消息,您轮询 SQS 的频率不会超过 20 秒。 如果有消息,您可以决定是频繁轮询(在消息到达后立即处理消息)还是始终按时间间隔处理它们(例如每 n 秒)。

需要注意的另一点是,您可以在单个 receiveMessages 请求中读取多达 10 条消息,这样也可以减少您对 SQS 的调用次数,从而降低成本。 正如上面的博客详细解释的那样,您可能会请求读取 10 条消息,但即使队列中有那么多消息,它也可能不会返回 10 条。

不过,总的来说,如果您希望在运行时关闭轮询,我会说您需要构建适当的挂钩和异常处理来关闭轮询,以防您使用 while(true) 类型的结构。

要考虑的另一个方面是您是想在主应用程序线程中轮询 SQS,还是想产生另一个线程。 因此,另一种选择可能是在主线程中创建一个带有单个线程的 ScheduledThreadPoolExecutor,以安排一个线程定期(每隔几秒)轮询 SQS,并且您可能不需要 while(true) 结构。

您缺少一些东西:

  • 使用receiveMessages(ReceiveMessageRequest)并设置等待时间以启用长轮询。
  • 将您的 AWS 调用包装在 try/catch 块中。 特别要注意OverLimitException ,如果您有太多的飞行消息,它可以从receiveMessages()抛出。
  • while循环的整个主体包装在它自己的 try/catch 块中,记录任何捕获的异常(不应该存在 - 这是为了确保您的应用程序不会因为 AWS 更改其 API 或您忽略而崩溃处理预期的异常)。

有关长轮询和可能的异常的更多信息,请参阅文档

至于使用异步客户端:你有什么特别的理由使用它吗? 如果没有,那么不要:单个接收器线程更容易管理。

如果您想使用 SQS 然后 lambda 来处理请求,您可以按照链接中给出的步骤进行操作,或者您始终使用 lambda 而不是 SQS 并为每个请求调用 lambda。

截至 2019 年,SQS 可以触发 lambda: https ://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html

我找到了一种主动监听队列的解决方案。 对于节点。 我使用了以下软件包并解决了我的问题。

sqs-消费者

链接https://www.npmjs.com/package/sqs-consumer

暂无
暂无

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

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