I have strange RabbitMQ behavior (as for me of course).
When I started spring boot web application, in my configuration I'm trying to create rabbit direct exchange:
#Bean
public DirectExchange exchange() {
return new DirectExchange(directExchangeName);
}
But when app started, I can't find this exchanger in RabbitMQ management. But it’s interesting, because in ApplicationContext I can see this bean.
This exchanger start to show in RabbitMQ management after first call to it.
Is I'm missing something? Or can it be issue with my configuration?
You need a RabbitAdmin #Bean to auto-declare exchanges, queues, bindings.
And, even then, the declarations will not occur until some component (listener container, template) opens a connection; the admin registers as a connection listener.
Related
Is there a way to create a RabbitMQ queue using spring cloud stream without having a consumer for the queue.
Our scenario is that we want to use the delay messaging strategy, so messages coming to the first queue would be held until expired and moved to a DLQ.
The application would be consuming the messages from the DLQ.
Wanted to check if there is a way we can use spring cloud stream to configure the queues, when we do not have a consumer for the first queue and it's just there to hold messages till expiry.
Yes; simply add a Queue bean (and binding if needed).
Boot auto configures a RabbitAdmin which will detect such beans when the connection is first established.
https://docs.spring.io/spring-amqp/docs/current/reference/html/#broker-configuration
#Bean
public Queue queue() {
return QueueBuilder.nonDurable("foo")
.autoDelete()
.exclusive()
.withArgument("foo", "bar")
.build();
}
We have observed in our enviornment as consumer from ActiveMQ UI get removed. We have very low traffic and observed as initially we have 3 consumer and those got each of them removed after interval of couple hours and once we restart our consumer it again refresh connection for couple more hours, we dont see any error in logs except:
Setup of JMS message listener invoker failed for destination 'queue-1' - trying to recover. Cause: The Consumer is closed
I use AWS ActiveMQ broker and don't see any error in the broker logs.
We use PoolConnectionFactory with ActiveMQConnectionFactory for creating pool of connection for our consumer as recommended. we are using ActiveMQ 5.15
#Bean
public PooledConnectionFactory pooledConnectionFactory() {
ActiveMQConnectionFactory activeMQConnectionFactory =
new ActiveMQConnectionFactory();
activeMQConnectionFactory.setBrokerURL(brokerUrl);
activeMQConnectionFactory.setUserName(username);
activeMQConnectionFactory.setPassword(password);
activeMQConnectionFactory.setTrustAllPackages(true);
ActiveMQPrefetchPolicy activeMQPrefetchPolicy = new ActiveMQPrefetchPolicy();
activeMQPrefetchPolicy.setQueuePrefetch(100);
//activeMQPrefetchPolicy.setQueuePrefetch();
activeMQConnectionFactory.setPrefetchPolicy(activeMQPrefetchPolicy);
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(activeMQConnectionFactory);
pooledConnectionFactory.setMaxConnections(poolSize);
return pooledConnectionFactory;
}
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(pooledConnectionFactory());
factory.setMessageConverter(jacksonJmsMessageConverter());
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
factory.setConcurrency("1-1");
factory.setErrorHandler(ActiveMQErrorHandler());
return factory;
}
#Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate(pooledConnectionFactory());
jmsTemplate.setMessageConverter(jacksonJmsMessageConverter());
return jmsTemplate;
}
#Bean
public Queue queue() {
return new ActiveMQQueue(queueName);
}
#Bean
public ErrorHandler ActiveMQErrorHandler() {
return t -> {
LOGGER.error("JMS_LISTENER_ERROR");
};
}
Given the information provided it sounds as though either the connection is dropping and the client isn't reporting that or the remote is closing the consumer on it's end which the pool will likely not notice until some user action is performed.
This is one of the gotchas of using a JMS pool which is that the pool doesn't have complete insight into what is going on with the client and therefore checking out a connection that's been sitting in the pool can result in obtaining a stale and no longer active connection due to the IO interruption that doesn't bubble up to the pool layer. One means of working around this would be to use the ActiveMQ client failover transport to allow it to automatically reconnect to the broker if the connection is dropped.
Another option you could try is to use the PooledJMS JMS connection pooling library which has some additional work done to attempt to validate failed connections and or closed resources sooner and match that with a ConnectionFactory that creates ActiveMQ connection's that use failover so that remotely closed resources like consumers could be caught in some cases.
Ultimately though your code will still need to deal with potential failure cases out of the JMS resources and retry where needed such as senders seeing security exceptions etc. The pooling bits don't make all your troubles go away, and in some cases they just introduce new one's you hadn't thought of yet.
Environment : Spring boot 1.4.0 , RMQ Client : 4.0.1 , CloudFoundry
I have application that has following simple rmq conn factory definition
#Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setUsername(user);
connectionFactory.setPassword(password);
connectionFactory.setHost(host);
connectionFactory.setPort(port);
return connectionFactory;
}
And simple listener method annotated with #RabbitListener. It works fine. Recently I have noticed couple times that even though I had 5k messages in queue it was not processing. On RMQ admin console I saw it has consumer too. I tried to took thread dump but didnt find anything interesting. Is there anything specially that I should look into thread dump (I have /dump endpoint). This happens anytime, so by the time I will notice logs will be scrolled (if anything) since other traffic like couple simple rest endpoint being invoked time to time. So that tells me that application itself is up, but just this listener part is kind of stuck or hung. I did search on this issue, there were some issues with this but fixed long back. (I don't want to go to pull model please :))
Please advise on how should I troubleshoot this. I have to wait again now to see this issue as I restarted application and it is working fine.
There is a known problem when the underlying rabbitmq connection factory has autoRecoveryEnabled set to true.
The 4.0.x client library now enables this by default but Spring AMQP doesn't need it; it has always had it's own recovery logic.
It is fixed in 1.6.8 and 1.7.1 (boot 1.4.0 comes with 1.6.1 by default). Boot 1.4.5 comes with 1.6.8.
1.7.1 also disables the option in the 4.0.x client (unless you specifically provide a rabbitmq connection factory).
Boot 1.5.2 comes with 1.7.1 by default.
Options:
Upgrade to a newer boot
Upgrade to a newer spring-amqp and spring-rabbit jar
Turn off autoRecovery in the underlying connection factory.
We have a requirement, where we create queues in rabbitMq on application startup with direct exchange, and then have to assign a single listener to each queue. We implemented that using Spring AMQP with the following configuration
#Bean(name= {"dispatcherListener"})
public SimpleMessageListenerContainer dispatcherListener() {
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory());
listenerContainer.setQueues(participantQueues());
listenerContainer.setMessageConverter(jsonMessageConverter());
listenerContainer.setMessageListener(subscriptionListener);
listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
listenerContainer.setAutoStartup(false);
return listenerContainer;
}
But then we faced a problem, with the above configuration. When we publish the message to multiple queues , then the listener is reading the messages serially from each queue. But we expected it to listen to messages from each queue independent of other queue parallely.
Can someone please guide me, where i went wrong ?
Any help would be appreciated
That's correct behavior, since the default concurrency is 1, therefore we have only one listener for all queue.
Just consider to increase that value for your configuration.
More info in the Reference Manual.
I need help with the Embedded ActiveMq and Spring Framework.
Problem is :-
I am using Embedded ActiveMQ with Spring framework JMS Support.
As part of development I have a component which publish messages to Virtual Topic. And i have another componet which subscribes messages from the topic.
Now problem here is the application which is subscribing messages is running in cluster environment i.e one master instance and one slave instance. Events which i have published are going to either master instance or slave instance. But i want messages to be subscribed by only master instance. Is there any way i can block slave instance not to subscribe events?
We have a system property set to differentiate master and slave instance.I have tried add condition by overriding createConnection method of ActiveMqConnectionFactory class.
if(master) {
ActiveMqConnectionFactory.createConnection}
else
return null.
in this case, DefaultMessageListener of Spring framework which we configured to listen events always trying to refresh connection, since i am returning null for slave, it is failing to create connection. the thread is going to infinite loop with 5000MS interval..
Is there any way i can say MessageListener to stop refreshing connection..
Please kindly help me to resolve this issue..
if the cluster is master/slave...then only one should be active at a given time...sounds like you have dual masters from an AMQ client perspective...
regardless, you can always use ActiveMQ security to control access to a given topic/queue based on connection credentials (see http://activemq.apache.org/security.html)