Spring boot 异步和共享兔子模板
我有如下的队列配置Spring boot 异步和共享兔子模板,spring-boot,rabbitmq,spring-amqp,spring-async,Spring Boot,Rabbitmq,Spring Amqp,Spring Async,我有如下的队列配置 @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(hostName); connectionFactory.setUsername(mqUsername); connectionFactory.setPassword(mqP
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(hostName);
connectionFactory.setUsername(mqUsername);
connectionFactory.setPassword(mqPassword);
connectionFactory.setVirtualHost(virtualHost);
return connectionFactory;
}
@Bean
RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}
@Bean
public AmqpAdmin amqpAdmin() {
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory());
return rabbitAdmin;
}
我有异步配置,比如
@EnableAsync
@Configuration
public class AsyncConfiguration implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
return taskExector();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
@Bean
public ThreadPoolTaskExecutor taskExector() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(10);
taskExecutor.initialize();
return taskExecutor;
}
}
在我的异步方法中,我使用amqp管理和兔子模板bean。因此,根据配置,我最多有10个线程执行任务,在应用程序挂起一段时间并使用下面的信息找到的执行器进行转储之后,我发现,在行号中使用rabbit template/amqp admin bean时似乎出现了死锁。
这种方法有什么问题吗?或者如何确保多个线程可以访问这些rabbitmqbean
版本:SpringBoot 1.4.0.RELEASE,Java8
我的服务是这样的
@Service
public class QDispatcherService implements DispatcherService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private AmqpAdmin amqpAdmin;
@Autowired
RabbitTemplate rabbitTemplate;
@Override
public void sendData(Data dataObject) throws Exception {
try {
//something on this properties , I have to check if queue exist or there are messages in it to decide to add message in other queue
Properties properties = amqpAdmin.getQueueProperties(queueName);
amqpAdmin.declareQueue(new Queue(queueName));
logger.info("***********************DEBUG 4***********************");
rabbitTemplate.convertAndSend(queueName, dataObject);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
________________________________________________________________________- 新痕迹
{
"threadName": "taskExector-10",
"threadId": 77,
"blockedTime": -1,
"blockedCount": 37,
"waitedTime": -1,
"waitedCount": 1113,
"lockName": "java.io.DataOutputStream@33111fc",
"lockOwnerId": 65,
"lockOwnerName": "taskExector-8",
"inNative": false,
"suspended": false,
"threadState": "BLOCKED",
"stackTrace": [
{
"methodName": "writeFrame",
"fileName": "SocketFrameHandler.java",
"lineNumber": 170,
"className": "com.rabbitmq.client.impl.SocketFrameHandler",
"nativeMethod": false
},
{
"methodName": "writeFrame",
"fileName": "AMQConnection.java",
"lineNumber": 542,
"className": "com.rabbitmq.client.impl.AMQConnection",
"nativeMethod": false
},
{
"methodName": "transmit",
"fileName": "AMQCommand.java",
"lineNumber": 104,
"className": "com.rabbitmq.client.impl.AMQCommand",
"nativeMethod": false
},
{
"methodName": "quiescingTransmit",
"fileName": "AMQChannel.java",
"lineNumber": 337,
"className": "com.rabbitmq.client.impl.AMQChannel",
"nativeMethod": false
},
{
"methodName": "transmit",
"fileName": "AMQChannel.java",
"lineNumber": 313,
"className": "com.rabbitmq.client.impl.AMQChannel",
"nativeMethod": false
},
{
"methodName": "basicPublish",
"fileName": "ChannelN.java",
"lineNumber": 686,
"className": "com.rabbitmq.client.impl.ChannelN",
"nativeMethod": false
},
{
"methodName": "basicPublish",
"fileName": "ChannelN.java",
"lineNumber": 668,
"className": "com.rabbitmq.client.impl.ChannelN",
"nativeMethod": false
},
{
"methodName": "invoke",
"fileName": null,
"lineNumber": -1,
"className": "sun.reflect.GeneratedMethodAccessor176",
"nativeMethod": false
},
{
"methodName": "invoke",
"fileName": "DelegatingMethodAccessorImpl.java",
"lineNumber": 43,
"className": "sun.reflect.DelegatingMethodAccessorImpl",
"nativeMethod": false
},
{
"methodName": "invoke",
"fileName": "Method.java",
"lineNumber": 498,
"className": "java.lang.reflect.Method",
"nativeMethod": false
},
{
"methodName": "invoke",
"fileName": "CachingConnectionFactory.java",
"lineNumber": 916,
"className": "org.springframework.amqp.rabbit.connection.CachingConnectionFactory$CachedChannelInvocationHandler",
"nativeMethod": false
},
{
"methodName": "basicPublish",
"fileName": null,
"lineNumber": -1,
"className": "com.sun.proxy.$Proxy166",
"nativeMethod": false
},
{
"methodName": "doSend",
"fileName": "RabbitTemplate.java",
"lineNumber": 1451,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "doInRabbit",
"fileName": "RabbitTemplate.java",
"lineNumber": 703,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate$3",
"nativeMethod": false
},
{
"methodName": "doExecute",
"fileName": "RabbitTemplate.java",
"lineNumber": 1394,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "execute",
"fileName": "RabbitTemplate.java",
"lineNumber": 1367,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "send",
"fileName": "RabbitTemplate.java",
"lineNumber": 699,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "convertAndSend",
"fileName": "RabbitTemplate.java",
"lineNumber": 767,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "convertAndSend",
"fileName": "RabbitTemplate.java",
"lineNumber": 754,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
}
每次发送时声明队列有点不寻常;也就是说,除了效率低下之外,它还应该发挥作用。堆栈跟踪表明我们被困在rabbit客户端中,等待队列声明的答复。我在多个线程使用同一通道时看到过这种情况,但在这里这种情况永远不会发生,因为当当前操作(管理、模板)完成时,通道总是返回到缓存,并且不能由多个线程使用
您可能希望尝试新的4.0.0.RC1 jar,因为它们现在添加了日志记录(3.x.x客户端中没有日志记录)。它可能有助于追踪情况。您必须向代码展示如何使用主问题中添加的
rabbitmplate
和RabbitAdmin
。你能和我们分享一些简单的启动应用程序吗?是的,我可以做一些东西,但是我有一个问题:1)兔子模板上的线程同步问题吗?作为。现在还不能报道本地新闻。2) 那个线程转储到底说了什么?3) 是否可能是因为队列被删除,我们尝试读取属性,所以导致了这种情况?4) 为什么它没有超时,如何在兔子豆上设置超时?当我有那个应用程序时,我将能够回答你。请解释创建/删除这些队列的原因。老实说,这不是制片人的责任。这是一个监听器部分,用于担心队列。谢谢,我将尝试使用新版本。我想排除这种情况,因为当我们试图获取队列道具或试图声明队列时,其他应用程序正在尝试使用/删除队列。正如u所说的,它正在等待rabbit的回复,这是否意味着由于我们的异步定制线程池,没有什么比锁定资源更好的了,我认为这不是wan而是wan来确认的。(最初的实验看起来,若我删除了服务的异步性质,那个么它的工作还可以,但需要做更多的测试)。以及为什么它没有超时如何为兔子操作或for设置我对兔子客户端的内部结构不太了解-你必须在rabbitmq用户google组上问这个问题。我以前只在有人试图通过一个传递返回消息的通道发送消息时看到过这种情况-这是一个类似的死锁-但我没有看到您在这里使用强制命令。我没有直接使用amqp lib,我使用的是spring ampq,它是1.6.1.RELEASE。(spring boot starter amqp spring boot ver 1.4.0.release)正确-spring rabbit以过渡方式拉入com.rabbitmq:amqp client:3.6.3
-您需要使用我给您指出的google group post中描述的坐标覆盖该依赖关系。顺便说一句,Spring Boot 1.4.2现在可用。问题仍然存在。之前提到的一些类似问题的链接在通道挂起和关闭的地方
{
"threadName": "taskExector-10",
"threadId": 77,
"blockedTime": -1,
"blockedCount": 37,
"waitedTime": -1,
"waitedCount": 1113,
"lockName": "java.io.DataOutputStream@33111fc",
"lockOwnerId": 65,
"lockOwnerName": "taskExector-8",
"inNative": false,
"suspended": false,
"threadState": "BLOCKED",
"stackTrace": [
{
"methodName": "writeFrame",
"fileName": "SocketFrameHandler.java",
"lineNumber": 170,
"className": "com.rabbitmq.client.impl.SocketFrameHandler",
"nativeMethod": false
},
{
"methodName": "writeFrame",
"fileName": "AMQConnection.java",
"lineNumber": 542,
"className": "com.rabbitmq.client.impl.AMQConnection",
"nativeMethod": false
},
{
"methodName": "transmit",
"fileName": "AMQCommand.java",
"lineNumber": 104,
"className": "com.rabbitmq.client.impl.AMQCommand",
"nativeMethod": false
},
{
"methodName": "quiescingTransmit",
"fileName": "AMQChannel.java",
"lineNumber": 337,
"className": "com.rabbitmq.client.impl.AMQChannel",
"nativeMethod": false
},
{
"methodName": "transmit",
"fileName": "AMQChannel.java",
"lineNumber": 313,
"className": "com.rabbitmq.client.impl.AMQChannel",
"nativeMethod": false
},
{
"methodName": "basicPublish",
"fileName": "ChannelN.java",
"lineNumber": 686,
"className": "com.rabbitmq.client.impl.ChannelN",
"nativeMethod": false
},
{
"methodName": "basicPublish",
"fileName": "ChannelN.java",
"lineNumber": 668,
"className": "com.rabbitmq.client.impl.ChannelN",
"nativeMethod": false
},
{
"methodName": "invoke",
"fileName": null,
"lineNumber": -1,
"className": "sun.reflect.GeneratedMethodAccessor176",
"nativeMethod": false
},
{
"methodName": "invoke",
"fileName": "DelegatingMethodAccessorImpl.java",
"lineNumber": 43,
"className": "sun.reflect.DelegatingMethodAccessorImpl",
"nativeMethod": false
},
{
"methodName": "invoke",
"fileName": "Method.java",
"lineNumber": 498,
"className": "java.lang.reflect.Method",
"nativeMethod": false
},
{
"methodName": "invoke",
"fileName": "CachingConnectionFactory.java",
"lineNumber": 916,
"className": "org.springframework.amqp.rabbit.connection.CachingConnectionFactory$CachedChannelInvocationHandler",
"nativeMethod": false
},
{
"methodName": "basicPublish",
"fileName": null,
"lineNumber": -1,
"className": "com.sun.proxy.$Proxy166",
"nativeMethod": false
},
{
"methodName": "doSend",
"fileName": "RabbitTemplate.java",
"lineNumber": 1451,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "doInRabbit",
"fileName": "RabbitTemplate.java",
"lineNumber": 703,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate$3",
"nativeMethod": false
},
{
"methodName": "doExecute",
"fileName": "RabbitTemplate.java",
"lineNumber": 1394,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "execute",
"fileName": "RabbitTemplate.java",
"lineNumber": 1367,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "send",
"fileName": "RabbitTemplate.java",
"lineNumber": 699,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "convertAndSend",
"fileName": "RabbitTemplate.java",
"lineNumber": 767,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
},
{
"methodName": "convertAndSend",
"fileName": "RabbitTemplate.java",
"lineNumber": 754,
"className": "org.springframework.amqp.rabbit.core.RabbitTemplate",
"nativeMethod": false
}