RabbitMQ prefetch ignored when consumer is Down and gets Up - rabbitmq

I'm getting my basicQos ignored when consumer is down and, after, consumer gets up. For instance, suppose that consumer is down and 5 messages arrives from a producer. If consumer is not running, these messages will be stored in disk (I think!) if exchanger/queue is (are) durable.
if I set basicQos as channel.basicQos(0, 3, true), my consumer receives more than 3 messages when it gets UP. Why?!?
On the other hand, everything works properly (only 3 messages are read from the queue) if consumer is running when it receives messages from the queues... My code is as follows:
factory = new ConnectionFactory();
factory.setHost(mRabbitMQHost); //may get server address from file configuration.
factory.setUsername(mRabbitMQUsername);
factory.setPassword(mRabbitMQPassword);
connection = factory.newConnection();
channel = connection.createChannel();
channel.exchangeDeclare("exchangeName", "direct", true); //True enables durability
consumer = new QueueingConsumer(channel);
for (QGQueues queue : QGQueues.values()) {
String queueName = queue.getQueueName();
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, "exchangeName", queue.getRoutingKey());
channel.basicConsume(queueName, false, consumer); //false enables ACK message to RabbitMQ server
}
channel.basicQos(0, 3, true);
Thanks!

My bet would be that you need to set the QoS before you do anything else.
Change your code to this order:
channel = connection.createChannel();
// set QoS immediately
channel.basicQos(0, 3, true);
channel.exchangeDeclare("exchangeName", "direct", true); //True enables durability
consumer = new QueueingConsumer(channel);
for (QGQueues queue : QGQueues.values()) {
String queueName = queue.getQueueName();
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, "exchangeName", queue.getRoutingKey());
channel.basicConsume(queueName, false, consumer); //false enables ACK message to RabbitMQ server
}
this will ensure the prefetch limit is set before you try to consume any messages.

Related

Sending message to queue in SingleActiveConsumer mode in MassTransit

I have registered receive endpoint in SingleActiveConsumer mode. However I can't find a way to send a message directly to queue by using sendEndpoint. I receive following error:
The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=406, text='PRECONDITION_FAILED - inequivalent arg 'x-single-active-consumer' for queue 'test' in vhost '/': received none but current is the value 'true' of type 'bool'',
I tried setting header "x-single-active-consumer"=true by using bus configurer:
var bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.Host("localhost", "/", h =>
{
h.Username("guest");
h.Password("guest");
});
cfg.ConfigureSend(a => a.UseSendExecute(c => c.Headers.Set("x-single-active-consumer", true)));
});
and directly on sendEndpoint:
await sendEndpoint.Send(msg, context => {
context.Headers.Set("x-single-active-consumer", true);
});
If you want to send directly to a receive endpoint in MassTransit, you can use the short address exchange:test instead, which will send to the exchange without trying to create/bind the queue to the exchange with the same name. That way, you decouple the queue configuration from the message producer.
Or, you could just use Publish, and let the exchange bindings route the message to the receive endpoint queue.

How to use micronaut rabbitmq client with BuiltinExchangeType TOPIC

I would like to use micronaut-rabbitmq to send messages between services via topics.
Therefore I've created an exchange, queues and bindings in the ChannelInitializer like this:
channel.exchangeDeclare("registration", BuiltinExchangeType.TOPIC, true)
channel.queueDeclare("user_new", true, false, false, null)
channel.queueBind("user_new", "registration", "user.new.#")
channel.queueDeclare("user_all", true, false, false, null)
channel.queueBind("user_all", "registration", "user.#")
When I try to send a message to the routingkey "user.new" it is not send to any of the queues.
#Binding("user.new")
override fun userCreated(event: UserCreatedEvent)
I would expect, that it is send to both of the queues because of the topics routingkeys.
If I rename the "user_new" queue to "user.new" the message is send to this queue. But as I want to have the message in both queues this is no option.
Any help would be appreciated!
Thank you
My Problem was, that I didn't declare the exchange on the #RabbitClient
After changing #RabbitClient to #RabbitClient("registration") everything works perfectly.

BizTalk receiving from RabbitMQ

I'm new to RabbitMQ but I have now installed onto a Windows server and have a couple of demo console apps (C#) that happily write to a read from a queue.
The following code works to pull messages from a queue called "RabbitPoCQueue_2" on the local server:
string queueName = "RabbitPoCQueue_2";
var factory = new ConnectionFactory();
bool keepGoing = true;
factory.HostName = "127.0.0.1";
try
{
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
const bool durable = false;
channel.QueueDeclare(queueName, durable, false, false, null);
System.Console.WriteLine(" [*] Waiting for messages.");
while (keepGoing)
{
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
System.Console.WriteLine(" [x] Received {0}", message);
};
channel.BasicConsume(queue: queueName,
autoAck: true,
consumer: consumer);
channel.BasicGet(queue: queueName, autoAck: true);
System.Console.WriteLine("Press Y to continue or any other key to exit");
keepGoing = System.Console.ReadKey().Key == ConsoleKey.Y;
}
}
}
I now need to configure a BizTalk (2016 FP3 CU5) receive location to do the same. I have ensured I've stopped the console receiver and that I have messages sat on the queue for BizTalk to collect.
I followed the article https://social.technet.microsoft.com/wiki/contents/articles/7401.biztalk-server-and-rabbitmq.aspx
Problem is, when I start the receive location, I get no errors but nothing is received.
The config for the WCF receive location can be seen below:
and here:
and here's a pic from the RabbitMQ management console showing messages sat on the queue:
When I look in the RabbitMQ log file, I see 2 rows on starting the receive location. I see 3 rows when starting the .Net console app (using RabbitMQ API), as shown below - first 2 rows are from BizTalk, last 3 from the console app:
2019-08-28 16:17:45.693 [info] <0.13361.2> connection <0.13361.2> ([::1]:16807 -> [::1]:5672): user 'guest' authenticated and granted access to vhost '/' ** Start of Receive location
2019-08-28 16:19:57.958 [info] <0.13452.2> accepting AMQP connection <0.13452.2> (127.0.0.1:17173 -> 127.0.0.1:5672)
2019-08-28 16:19:58.026 [info] <0.13452.2> connection <0.13452.2> (127.0.0.1:17173 -> 127.0.0.1:5672): user 'guest' authenticated and granted access to vhost '/' ** Receive from command line
2019-08-28 18:56:26.267 [info] <0.13452.2> closing AMQP connection <0.13452.2> (127.0.0.1:17173 -> 127.0.0.1:5672, vhost: '/', user: 'guest')
2019-08-28 18:56:39.815 [info] <0.17923.2> accepting AMQP connection <0.17923.2> (127.0.0.1:41103 -> 127.0.0.1:5672)
Can anyone spot where I went wrong?

RabbitMQ queue gets blank randomly with around 5K messages remaining

I have a queue to which a lot of messages are published (~10K). Connected to this queue are multiple consumers with the following code in codeigniter using the php-amqplib library
public function processQueue()
{
// Make connection
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
// Make channel
$channel = $connection->channel();
// Declare queue
$channel->queue_declare(QUEUE_NAME, false, false, false, false);
// PHP callable
$callback = function ($msg) {
//DO MESSAGE PROCESSING HERE
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};
$channel->basic_consume(AGENTS_QUEUE_PROCESSING, '', false, true, false, false, $callback);
// While queue is empty, wait
while (count($channel->callbacks)) {
// Wait
$channel->wait();
}
// Close channel and connection
$channel->close();
$connection->close();
}
The messages gets filled up and are simultaneously consumed by multiple such consumers. I've observed that with some 5-6k messages remaining (i.e. after consuming around 4-5k) messages, the queue suddenly gets empty with the consumers idling and waiting for more messages. Also, there is a sudden drop at this point in time in the total number of messages on the RabbitMQ Management web panel.
I've tried making the queue with the durable parameter but the problem seems to be the same. What could be the issue and its resolution?

Get IP of producers sending messages to queue/exchange

For troubleshooting purpose I want to get list of producers sending messages to a particular queue or exchange. I dont see any option in rabbitmq console to get the above details. Some producers are piling up a paricular queue, I am trying to figure out the IP of producer piling up messages in the queue.
Can any one please guide me on this.
you don't have this information by default, but you can use the message headers to do that.
for example:
string message = "Hello World!";
var body = Encoding.UTF8.GetBytes(message);
var properties = new BasicProperties();
properties.Headers = new Dictionary<string, object>();
properties.Headers.Add("senderip", InetAddress.getLocalHost().getHostAddress());
properties.Headers.Add("custominfo", "info" );
channel.BasicPublish(exchange: "", routingKey: "mykey", basicProperties: properties,body: body);
When you recevice the message you can decode the headers