在下面的示例中,我将max和core pool size设置为1.但是没有消息正在处理中。当我启用调试日志时,我能够看到从SQS中提取的消息,但我猜它没有被处理/删除。但是,当我将核心和最大池大小增加到2时,似乎会处理消息。
修改
我相信Spring可能为接收器分配一个线程,该接收器从队列中读取数据,因此无法将线程分配给正在处理消息的侦听器。当我将corepoolsize增加到2时,我看到消息正在从队列中读取。当我添加另一个监听器(用于死信队列)时,我遇到了同样的问题 - 由于没有处理消息,因此2个线程是不够的。当我将corepoolsize增加到3时,它开始处理消息。我假设在这种情况下,分配了1个线程来读取队列中的消息,并为2个侦听器分配了1个线程。
@Configuration
public class SqsListenerConfiguration {
@Bean
@ConfigurationProperties(prefix = "aws.configuration")
public ClientConfiguration clientConfiguration() {
return new ClientConfiguration();
}
@Bean
@Primary
public AWSCredentialsProvider awsCredentialsProvider() {
ProfileCredentialsProvider credentialsProvider = new ProfileCredentialsProvider("credential");
try {
credentialsProvider.getCredentials();
System.out.println(credentialsProvider.getCredentials().getAWSAccessKeyId());
System.out.println(credentialsProvider.getCredentials().getAWSSecretKey());
} catch (Exception e) {
throw new AmazonClientException(
"Cannot load the credentials from the credential profiles file. " +
"Please make sure that your credentials file is at the correct " +
"location (~/.aws/credentials), and is in valid format.",
e);
}
return credentialsProvider;
}
@Bean
@Primary
public AmazonSQSAsync amazonSQSAsync() {
return AmazonSQSAsyncClientBuilder.standard().
withCredentials(awsCredentialsProvider()).
withClientConfiguration(clientConfiguration()).
build();
}
@Bean
@ConfigurationProperties(prefix = "aws.queue")
public SimpleMessageListenerContainer simpleMessageListenerContainer(AmazonSQSAsync amazonSQSAsync) {
SimpleMessageListenerContainer simpleMessageListenerContainer = new SimpleMessageListenerContainer();
simpleMessageListenerContainer.setAmazonSqs(amazonSQSAsync);
simpleMessageListenerContainer.setMessageHandler(queueMessageHandler());
simpleMessageListenerContainer.setMaxNumberOfMessages(10);
simpleMessageListenerContainer.setTaskExecutor(threadPoolTaskExecutor());
return simpleMessageListenerContainer;
}
@Bean
public QueueMessageHandler queueMessageHandler() {
QueueMessageHandlerFactory queueMessageHandlerFactory = new QueueMessageHandlerFactory();
queueMessageHandlerFactory.setAmazonSqs(amazonSQSAsync());
QueueMessageHandler queueMessageHandler = queueMessageHandlerFactory.createQueueMessageHandler();
return queueMessageHandler;
}
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setMaxPoolSize(1);
executor.setThreadNamePrefix("oaoQueueExecutor");
executor.initialize();
return executor;
}
@Bean
public QueueMessagingTemplate messagingTemplate(@Autowired AmazonSQSAsync amazonSQSAsync) {
return new QueueMessagingTemplate(amazonSQSAsync);
}
}
监听器配置
@SqsListener(value = "${oao.sqs.url}", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
public void onMessage(String serviceData, @Header("MessageId") String messageId, @Header("ApproximateFirstReceiveTimestamp") String approximateFirstReceiveTimestamp) {
System.out.println(" Data = " + serviceData + " MessageId = " + messageId);
repository.execute(serviceData);
}
答案 0 :(得分:6)
通过设置corePoolSize
和maximumPoolSize
相同,您可以创建fixed-size thread pool
。记录了here
设置maxPoolSize
隐式允许删除任务。
但是,默认队列容量为Integer.MAX_VALUE
,出于实际目的,该容量为无穷大。
值得注意的是ThreadPoolTaskExecutor
下面使用ThreadPoolExecutor
,这有一种不同寻常的排队方法,在the docs中有描述:
如果
corePoolSize
个或更多线程正在运行,则执行程序总是更喜欢排队请求而不是添加新线程。
这意味着maxPoolSize
仅在队列已满时才相关,否则线程数将永远不会超过corePoolSize
。
例如,如果我们向线程池提交永远不会完成的任务:
corePoolSize
提交将分别开始一个新主题; maxPoolSize
; 排队 - 阅读docs
任何BlockingQueue
都可用于转移和保留已提交的任务。此队列的使用与池大小调整相互作用:
Unbounded queues
。使用无界队列(例如a 没有预定义容量的LinkedBlockingQueue
将导致新的 在所有corePoolSize线程都忙的情况下排队的任务。 因此,永远不会创建corePoolSize
个线程。 (而且 因此maximumPoolSize
的值没有任何影响。)
corePoolSize
,请创建一个新线程
线程来运行一个新任务。corePoolSize
,将任务放入队列。maxPoolSize
,创建一个新线程来运行任务。maxPoolSize
,拒绝任务。