Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring Cloud SQS消费阻塞,直到处理完所有消息_Java_Spring_Spring Boot_Spring Cloud_Amazon Sqs - Fatal编程技术网

Java Spring Cloud SQS消费阻塞,直到处理完所有消息

Java Spring Cloud SQS消费阻塞,直到处理完所有消息,java,spring,spring-boot,spring-cloud,amazon-sqs,Java,Spring,Spring Boot,Spring Cloud,Amazon Sqs,我们正在使用它与SQS进行交互。我们使用@SqsListener注释从队列中提取消息。我们有deletionPolicy=NEVER,这意味着我们手动确认所收到的所有消息 我们的问题是,SimpleMessageListenerContainer(处理队列中消息的处理)等待所有工作线程完成,然后再从队列中提取更多消息 换句话说,我们看到的是: 从队列中提取10条消息 启动10个线程进行工作 执行工作的线程之一在缓慢的IO调用中被阻塞 应用程序现在被阻止从队列中获取更多消息,因此在缓慢的调用完成

我们正在使用它与SQS进行交互。我们使用
@SqsListener
注释从队列中提取消息。我们有
deletionPolicy=NEVER
,这意味着我们手动确认所收到的所有消息

我们的问题是,
SimpleMessageListenerContainer
(处理队列中消息的处理)等待所有工作线程完成,然后再从队列中提取更多消息

换句话说,我们看到的是:

  • 从队列中提取10条消息
  • 启动10个线程进行工作
  • 执行工作的线程之一在缓慢的IO调用中被阻塞
  • 应用程序现在被阻止从队列中获取更多消息,因此在缓慢的调用完成之前,它根本无法做更多的工作
我们可以在
SimpleMessageListener.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
是本地包


有什么方法可以避免这种行为吗?

保持消息轮询线程的是
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
函数且没有可用线程时阻塞


这是大多数实现的工作方式,但值得检查您的实现。

谢谢,但我们如何真正覆盖
AsynchronousMessageListener
?它是私有的..抱歉,我没有意识到这不是您的代码:-(…好吧,在这种情况下,假设spring不允许您重写该行为,我想实现您自己的队列轮询代码会更容易…您可以重写
startQueue(String queueName,QueueAttributes QueueAttributes)
,对吗?