我以非常简单的方式使用 Amazon SQS 队列。通常,消息被写入并立即可见和读取。有时,会写入一条消息,并在队列中保留运行中(不可见)几分钟。我可以从控制台看到它。接收消息等待时间为 0,默认可见性为 5 秒。它将保持这种状态几分钟,或者直到写入新消息以某种方式释放它。延迟几秒可以,但超过 60 秒就不行了。
有 8 个读取器线程始终进行长轮询,因此并不是某些东西没有尝试读取它,而是它们正在尝试读取它。
编辑:需要明确的是,所有消费者读取都不会返回任何消息,并且无论控制台是否打开都会发生这种情况。在这种情况下,只涉及一条消息,并且它只是位于队列中,对消费者来说是不可见的。
有其他人看到过这种行为吗?我可以采取哪些措施来改进它?
这是我正在使用的java sdk:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.5.2</version>
</dependency>
这是执行读取的代码(max=10,maxwait=0 启动配置):
void read(MessageConsumer consumer) {
List<Message> messages = read(max, maxWait);
for (Message message : messages) {
if (tryConsume(consumer, message)) {
delete(message.getReceiptHandle());
}
}
}
private List<Message> read(int max, int maxWait) {
AmazonSQS sqs = getClient();
ReceiveMessageRequest rq = new ReceiveMessageRequest(queueUrl);
rq.setMaxNumberOfMessages(max);
rq.setWaitTimeSeconds(maxWait);
List<Message> messages = sqs.receiveMessage(rq).getMessages();
if (messages.size() > 0) {
LOG.info("read {} messages from SQS queue",messages.size());
}
return messages;
}
发生这种情况时,“read ..”的日志行永远不会出现,这导致我进入控制台并查看该消息是否存在,事实确实如此。
最佳答案
听起来您误解了您所看到的内容。
“正在传输”的消息不是待传递的消息,它们是已经传递但消费者没有进一步采取行动的消息。
Messages are considered to be in flight if they have been sent to a client but have not yet been deleted or have not yet reached the end of their visibility window.
当消费者收到一条消息时,它必须在某个时刻删除该消息,或者向 increase the timeout 发送请求。对于该消息;否则,超时后该消息将再次可见。如果消费者未能执行其中一项操作,该消息将自动再次可见。可见性超时是消费者在必须完成其中一件事情之前的时间。
在没有其他东西已经收到消息的情况下,消息不应该“正在传输”——但是“某些东西”可以包括控制台本身,正如您在选择“查看/删除消息”时看到的弹出窗口中所注意到的那样”在控制台中(除非您已经选中“不再显示此内容”复选框):
Messages displayed in the console will not be available to other applications until the console stops polling for messages.
当控制台从“查看/删除消息”屏幕观察队列时,控制台中显示的消息“正在运行”。
没有明显意义的部分是,如果您的默认可见性超时仅为 5 秒,并且代码中没有任何内容增加该超时,则消息会“持续几分钟”……但是……这可以解释几乎完全是由于您的消费者没有正确处理消息,导致消息超时并立即重新传递,给人的印象是消息的单个实例仍在运行中,而事实上,消息正在短暂地转换回可见状态,但几乎立即就被另一名消费者认领,并再次将其带回飞行中。
关于amazon-web-services - 为什么 SqS 消息有时会保留在队列中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19792881/