我们正在使用Spring Cloud AWS与SQS进行互动。我们使用@SqsListener
注释从我们的队列中提取消息。我们有deletionPolicy = NEVER
,这意味着我们手动确认我们选择的所有邮件。
我们的问题是SimpleMessageListenerContainer
(处理来自队列的消息处理)等待所有工作线程完成,然后再从队列中选择更多消息。
换句话说,我们所看到的是:
我们可以看到SimpleMessageListenerContainer.AsynchronousMessageListener
中负责此
@Override
public void run() {
while (isQueueRunning()) {
try {
ReceiveMessageResult receiveMessageResult = getAmazonSqs().receiveMessage(this.queueAttributes.getReceiveMessageRequest());
CountDownLatch messageBatchLatch = new CountDownLatch(receiveMessageResult.getMessages().size());
for (Message message : receiveMessageResult.getMessages()) {
if (isQueueRunning()) {
MessageExecutor messageExecutor = new MessageExecutor(this.logicalQueueName, message, this.queueAttributes);
getTaskExecutor().execute(new SignalExecutingRunnable(messageBatchLatch, messageExecutor));
} else {
messageBatchLatch.countDown();
}
}
try {
messageBatchLatch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
} catch (Exception e) {
getLogger().warn("An Exception occurred while polling queue '{}'. The failing operation will be " +
"retried in {} milliseconds", this.logicalQueueName, getBackOffTime(), e);
try {
//noinspection BusyWait
Thread.sleep(getBackOffTime());
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
理想情况下,我们希望消息监听器不断从队列中选择消息进行处理。
我们似乎无法实现自己的MessageListenerContainer
,因为AbstractMessageListenerContainer
是本地包。
这种行为有什么办法吗?
答案 0 :(得分:0)
持有消息轮询线程的是messageBatchLatch.await()
语句。似乎只需移除闩锁即可。类似的东西:
@Override
public void run() {
while (isQueueRunning()) {
try {
ReceiveMessageResult receiveMessageResult = getAmazonSqs().receiveMessage(this.queueAttributes.getReceiveMessageRequest());
for (Message message : receiveMessageResult.getMessages()) {
if (isQueueRunning()) {
MessageExecutor messageExecutor = new MessageExecutor(this.logicalQueueName, message, this.queueAttributes);
getTaskExecutor().execute(new SignalExecutingRunnable(messageExecutor));
}
}
} catch (Exception e) {
getLogger().warn("An Exception occurred while polling queue '{}'. The failing operation will be " +
"retried in {} milliseconds", this.logicalQueueName, getBackOffTime(), e);
try {
//noinspection BusyWait
Thread.sleep(getBackOffTime());
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
如果您的TaskExecutor
实施,这将有效:
- 有一个固定大小的线程池
- 调用execute
函数且没有线程可用时阻塞。
这是大多数实现的工作方式,但值得检查一下。