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.
Is it possible to configure MassTransit to not create a RabbitMQ exchange for a consumer host? My RabbitMQ user has not enough rights to declare an exchange at the host where the consuming queue is located, so MassTransit fails to start with the following error:
Unhandled Exception: MassTransit.RabbitMqTransport.RabbitMqConnectionException:
Operation interrupted ---> RabbitMQ.Client.Exceptions.OperationInterruptedExcept
ion: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, c
ode=403, text="ACCESS_REFUSED - access to exchange '***' i
n vhost '***' refused for user '***'", classId=
40, methodId=10, cause=
Here is the code that I use:
var bus = Bus.Factory.CreateUsingRabbitMq(sbc =>
{
var host = sbc.Host(host: "***", port: 5671, virtualHost: "***", configure: configurator =>
{
configurator.UseSsl(sslConfigurator =>
{
sslConfigurator.Certificate = certificate;
sslConfigurator.UseCertificateAsAuthenticationIdentity = true;
sslConfigurator.ServerName = "***";
});
});
sbc.ReceiveEndpoint(host, "***", endpointConfigurator =>
{
endpointConfigurator.Consumer<UpdateCustomerConsumer>();
});
});
I am testing the ConfirmCallback, ReturnCallback flows for a simple Publisher->Exchange->queue and listener model. I have set the publisherConfirms, publisherReturns, mandatory to true . I published a new message to an existing exchange with an invalid queue name. As expected, I received the callback to the ReturnCallback.returnedMessage method. However I received a callback to the ConfirmCallback.confirm method as well. As i understand since the queue name is invalid only the ReturnCallback.returnedMessage method should have received the callback. Why does ConfirmCallback.confirm method gets invoked? I have tested the scenario many times and I have received the same result. Please check the below code snippets and the log file for your understanding and let me know if something is wrong.
rabbitTemplate.setMandatory(true);
rabbitTemplate.setConfirmCallback(new ConfirmCallback() {
#Override
public void confirm(final CorrelationData correlationData, final boolean ack,
final String cause) {
System.out.println("confirmCallback received with correlationData, ack, cause" + correlationData+ cause + ack);
if (null != confirmCallbackUser) {
confirmCallbackUser.confirm(correlationData.getId(), ack, cause);
} });
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback()
#Override
public void returnedMessage(final Message message, final int replyCode,
final String replyText, final String exchange, final String routingKey) {
Message msg = new Message(message);
try {
System.out.println("returnCallBackUser received with message, replyCode, replyText, exchange, routingKey" + message + replyCode + replyText+ exchange + routingKey);
returnCallBackUser.returnedMessage(msg, replyCode, replyText, exchange,
routingKey);
} catch (MessagingException e) {
System.out.println("returnCallBackUser exception : " + e.getMessage());
e.printStackTrace();
}
System.err.println(" Message Returned");
}
Logs
40053 [https-openssl-nio-8443-exec-6] DEBUG c.s.n.f.s.messaging.MessImpl **- Control reached send()**
40056 [https-openssl-nio-8443-exec-6] DEBUG o.s.a.r.c.CachingConnectionFactory - Creating cached Rabbit Channel from PublisherCallbackChannelImpl: AMQChannel(amqp://guest#127.0.0.1:5672/,2)
40056 [https-openssl-nio-8443-exec-6] DEBUG o.s.a.r.s.PublisherCallbackChannelImpl - Added listener org.springframework.amqp.rabbit.core.RabbitTemplate#7c8f1db1
40057 [https-openssl-nio-8443-exec-6] DEBUG o.s.amqp.rabbit.core.RabbitTemplate - Added pubsub channel: Cached Rabbit Channel: PublisherCallbackChannelImpl: AMQChannel(amqp://guest#127.0.0.1:5672/,2), conn: Proxy#6bc6056e Shared Rabbit Connection: SimpleConnection#69225b5 [delegate=amqp://guest#127.0.0.1:5672/, localPort= 60962] to map, size now 1
40057 [https-openssl-nio-8443-exec-6] DEBUG o.s.amqp.rabbit.core.RabbitTemplate **- Executing callback on RabbitMQ Channel: Cached Rabbit Channel:** PublisherCallbackChannelImpl: AMQChannel(amqp://guest#127.0.0.1:5672/,2), conn: Proxy#6bc6056e Shared Rabbit Connection: SimpleConnection#69225b5 [delegate=amqp://guest#127.0.0.1:5672/, localPort= 60962]
40061 [https-openssl-nio-8443-exec-6] DEBUG o.s.amqp.rabbit.core.RabbitTemplate **- Publishing message on exchange [ControlExchange], routingKey = [invalidQueue]**
40064 [https-openssl-nio-8443-exec-6] DEBUG c.s.n.f.s.messaging.MessImpl - **Control moving out of send()**
***returnCallBackUser received with message,*** replyCode, replyText, exchange, routingKey(Body:'[B#294b5bb4(byte[91])' MessageProperties [headers={IDENTITY=TOMCAT_CONTROL}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=[80, 114, 111, 100, 117, 99, 101, 114], correlationIdString=null, replyTo=ControlExchange/ComAckQueue, contentType=application/octet-stream, contentEncoding=null, contentLength=0, deliveryMode=null, receivedDeliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=null, receivedExchange=null, receivedRoutingKey=null, receivedDelay=null, deliveryTag=0, messageCount=null, consumerTag=null, consumerQueue=null])312NO_ROUTEControlExchangeinvalidQueue
40066 [AMQP Connection 127.0.0.1:5672] INFO c.s.n.f.s.m.CallBackRecReplyInterfaceTemplate - Message {"Test":"abcd","Role":"abcd","Id":"1111","request":"Accepted","De":"invalidQueue"} replyCode-> 312breplyText-> NO_ROUTE exchange-> Exchange routingKey-> invalidQueue
**Message Returned**
40066 [AMQP Connection 127.0.0.1:5672] DEBUG o.s.a.r.s.PublisherCallbackChannelImpl - **PublisherCallbackChannelImpl: AMQChannel(amqp://guest#127.0.0.1:5672/,2) PC:Ack:1:false**
40067 [AMQP Connection 127.0.0.1:5672] DEBUG o.s.a.r.s.PublisherCallbackChannelImpl - **Sending confirm PendingConfirm [correlationData=CorrelationData [id=corrlDat]]
confirmCallback received with correlationData, ack, causeCorrelationData [id=corrlDat]nulltrue**
40067 [AMQP Connection 127.0.0.1:5672] INFO c.s.n.f.s.m.CallbackConfirmImplTempl - **ACK->truecause->nullcorr id corrlDat
40067 [AMQP Connection 127.0.0.1:5672] INFO c.s.n.f.s.messaging.MessagingImpl - ACK->truecause->nullcorr id corrlDat**
Publisher Confirms calls when broker finished handle it. In case of wrong queue, broker sends confirm when it will verify that message won't route. See documentation in section "When will messages be confirmed".
I'm using rabbitmq 3.6.6 using the docker image "rabbitmq:3"
Whenever I add a new consumer to my RabbitMQ queue it hangs from anywhere to 10 seconds 10 hours.
Below is an example of code used to get the error. I also get this error in Go. So it's not library dependant.
<?php
include(__DIR__."/vendor/autoload.php");
print "Start" . PHP_EOL;
$connection = new \PhpAmqpLib\Connection\AMQPStreamConnection('xxxx', 5697, 'guest', 'guest');
$channel = $connection->channel();
$callback = function($msg) {
echo " [x] Received ", $msg->body, "\n";
};
$channel->basic_consume('repositories', '', false, false, false, false, $callback);
while(count($channel->callbacks)) {
$channel->wait();
}
When I look at the logs I see
=INFO REPORT==== 31-Jan-2017::21:14:33 ===
accepting AMQP connection <0.891.0> (10.32.0.1:54216 -> 10.44.0.3:5672)
=INFO REPORT==== 31-Jan-2017::21:14:34 ===
accepting AMQP connection <0.902.0> (10.32.0.1:54247 -> 10.44.0.3:5672)
When I do list_consumer during via rabbitmqctl I see the consumer in the list, yet no messages are processed by it.
It turns out I needed to set the Qos setting.
Some more information can be found at:
http://www.rabbitmq.com/consumer-prefetch.html
https://github.com/streadway/amqp/blob/master/channel.go#L576
I am working on a fun project which requires me to learn message queues and websockets. I am trying to connect browsers via websockets to an instance of rabbitmq using sockjs rather than pure websockets. On rabbit I have activated the plugins for stomp and web_stomp (web_stomp is required when using sockjs).
The problem I am running into is that while the call from the browser seems to be working properly because a very brief connection to Rabbit is made through the webstomp/stomp connection but after 2 or 3 seconds the connection is dropped by Rabbit.
This is confirmed by the rabbitmq logs:
=INFO REPORT==== 11-Jul-2016::23:01:54 ===
accepting STOMP connection (192.168.1.10:49746 -> 192.168.1.100:55674)
=INFO REPORT==== 11-Jul-2016::23:02:02 ===
closing STOMP connection (192.168.1.10:49746 -> 192.168.1.100:55674)
This is the browser code that connects to RabbitMQ via the webstomp plugin:
var url = "http://192.168.1.100:55674/stomp";
var ws = new SockJS(url);
var client = Stomp.over(ws);
var header = {
login: 'test',
passcode: 'test'
};
client.connect(header,
function(){
console.log('Hooray! Connected');
},
function(error){
console.log('Error connecting to WS via stomp:' + JSON.stringify(error));
}
);
Here is the Rabbit config:
[
{rabbitmq_stomp, [{default_user, [{login, "test"},
{passcode, "test"}
]
},
{tcp_listeners, [{"192.168.1.100", 55674}]},
{heartbeat, 0}
]
}
]
I have been over the Rabbit docs a million times but this feels like something simple that I am overlooking.
Resolved. After combing through the logs I realized that web_stomp was listening on port 15674 so I changed the config file to reflect that. I swear I had made that change at some point but it did not seem to make a difference.
One of the late changes I made before sending out my request was to turn off heartbeat. Everything I have read states that sockjs does not support heartbeat and that there were suggestions to turn it off rather than use the default. In addition to turning off heartbeat in the config file I also added this to the browser code:
client.heartbeat.outgoing=0;
client.heartbeat.incoming=0;