[英]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)
并设置等待时间以启用长轮询。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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.