We are using RabbitMQ and MassTransit as our messaging infrastructure in out application.
I have a scenario where my consumer needs to stop processing messages for a while and then restarted at some later point.
I can successfully stop the bus and consumer stops processing further messages but when I restart the bus it says bus already started, but the consumer won't pickup any more messages for further processing
Sample code looks like
var iBusControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(new Uri("rabbitmq://localhost"), h =>
{
h.Username("guest");
h.Password("guest");
});
if (linkConsumer)
cfg.ReceiveEndpoint("TestMessage_Queue", x =>
{
x.Consumer<TestMessageConsumer>();
});
});
iBusControl.Start();
// Consumer starts processing messages
// later on in the code I call stop on the same bus instance
iBusControl.Stop();
// Consumer stops processing messages
// later on in the code I call start again on the bus instance
iBusControl.Start();
// Masstransit also says, bus already started
// But the consumer won't pick up any further messages for processing.
Bus if I create a new instance of the bus same as the first block of my code and call start on it, it will connect the consumer correctly and message processing starts again. Few questions/confusions
Is this the expected behaviour?
Does stopping the bus removes all receive endpoint configuration?
Why can't I start the bus after stopping it?
Using MassTransit 5.3.3 with RabbitMQ 3.6.14 Erlang 20.1
With the release of masstransit v7.1.0, the bus can be restarted after being stopped. Before that, this was not possible.
From the release notes:
Since MassTransit's inception, it has never been possible to Start a bus that was previously Started and then Stopped. With this release, a bus can now be started, stopped, started, and stopped, and started, and stopped...
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();
}
I use MassTransit and RabbitMQ quorum queue for application integration. I send message using
var endpoint = await _bus.GetSendEndpoint(new Uri("exchange:TestCommand"));
await endpoint.Send(command1, stoppingToken);
If "receiver application" doesn't ever start, queue won't be created and all sent messages will be lost.
If I use prefix queue for send:
var endpoint = await _bus.GetSendEndpoint(new Uri("queue:TestCommand"));
await endpoint.Send(command, stoppingToken);
classic queue will be created (not quorum). And I can't change queue type later.
I don't want to think about "receiver application" starting moment and I don't want to loose sent messages. How I can create RabbitMQ quorum queue by sender application using MassTransit?
The general guidance is simple, don't couple your producers to your consumers.
You can start the receiver first so that it configures the queue properly (including the quorum settings).
Or you can set the Mandatory flag (RabbitMQ specified) so that Send throws an exception if the message is not delivered to a queue, and return to sending to the exchange.
I need to start a queue in OpenEJB in a "paused" state so no messages are processed by the consumer until some related data is available. I can programmatically pause the queue as shown here, so if there was some initializer function that is called when a queue is created I could use that method. The queue configuration documentation does not seem to support setting the paused state. Any ideas on how to configure the queue upon creation?
If you read the thread you link you will see a queue is not paused but a broker can be.
In TomEE broker is created from a factory using a spi (in tomee classloader so tomee/lib by default) so you can write your own if that's an option starting programmatically when you are ready.
Now I suspect you don't want to start connectors with the container but it is not an issue to start the broker. Said otherwise you don't want to be connected to any other machine through JMS to not receive anything but if JMS is started and deployed it is ok.
In such a case you can just not configure any connector on the broker and add them when ready. You can find brokers doing:
new org.apache.openejb.resource.activemq.ActiveMQ5Factory().getBrokers()
I'm doing
IBusControl.Stop()
to let my consumer stop listening, but it keeps going. When in the debugger I'm still getting in the Consumer method where the published methods are read. Am I missing something? Or how can I disconnect from the bus or the queue?
I want to consume the messages in my Storm Spout from a rabbitMq Queue.
Now , we are using Spring AMQP to send and receive messages from RabbitMq asynchronously.
Spring AMQP provides mechanism(either creating a listener or using annotation #RabbitListner) to read message from the queue .
The problem is I can have a Listener to read the message from the Queue. But how do I send this message to my Storm Spout which is running on storm cluster ?
The topology will start a cluster, but in my nextTuple() method of my spout , I need to read message from this Queue. Can Spring AMQP be used here ?
I have a listener configured to read message from the queue:
#RabbitListener(queues = "queueName")
public void processMessage(QueueMessage message) {
}
How can the above message received at the listener be sent to my spout running on a cluster .
Alternatively , how can a spout's nextTuple() method have this method inside it ? Is it possible
I am using Java as a language here.
You can read messages on-demand (rather than being message-driven) by using one of the RabbitTemplate receive or receiveAndConvert methods.
By default, they will return null if there is no message in the queue.
EDIT:
If you set the receiveTimeout (available in version 1.5 or above), the receive methods will block for that time (it uses an async consumer internally and does not poll).
But it's still not as efficient as the listener because a new consumer is created for each method; to use a listener you would need to use some internal blocking mechanism in nextTuple() (e.g. a BlockingQueue) to wait for messages.