[rabbitmq-discuss] pika and node.amqp interop
Michael Bridgen
mikeb at rabbitmq.com
Sat Jan 22 10:46:48 GMT 2011
Hi Dan,
> I am new to rabbitmq. I got the python "getting started" examples to
> work just fine.
> I would like to be able to send messages between node.js (using
> node.amqp) and python/pika.
>
> I can successfully receive a message in node.js using this code:
>
> [receiver - node.js]
> var sys = require('sys');
> var amqp = require('./amqp');
>
> var connection = amqp.createConnection({ host: 'localhost' });
>
> // Wait for connection to become established.
> connection.addListener('ready', function () {
> // Create a queue and bind to all messages.
> // Use the default 'amq.topic' exchange
>
> var q = connection.queue('my-queue');
> // Catch all messages
> q.bind('#');
>
> // Receive messages
> q.subscribe(function (message) {
> // Print messages to stdout
> sys.puts(sys.inspect(message));
> });
> });
>
> [sender - python/pika]
> #!/usr/bin/env python
> import pika
>
> connection = pika.AsyncoreConnection(pika.ConnectionParameters(
> host='localhost'))
> channel = connection.channel()
>
>
> channel.basic_publish(exchange='',
> routing_key='my-queue',
> body='Hello World!')
> print " [x] Sent 'Hello World!'"
> connection.close()
You should be aware that node-amqp, at least Ryan's original and most
forks of it, make some unorthodox choices for parameter defaults and
behaviour, which to be fair are probably inherited from the EventMachine
AMQP client.
In particular, the exchange that's published or bound to, if none is
given, is "amq.topic". This is directly at odds with AMQP, for which an
empty exchange name means the "default exchange" defined in the
specification; that is, route directly to the queue named in the routing
key.
So your example above is working by coincidence -- you don't need to
bind the queue in the node.js code, since your Python code is
effectively sending straight to the queue. I.e., the node.js code sets up
(amq.topic) --"#"--> [ | | my-queue | | ]
but the message sent in the Python code actually follows
(default) --"my-queue"--> [ | | my-queue | | ]
> But I can't go the other way. I'm not sure that the message sent by
> node.js is going anywhere. I've looked at the unit tests for node.amqp
> (they all pass) but there is something I am missing, probably to do with
> exchanges or something. I'd like to do something like this:
>
> [sender - node.js]
> var sys = require('sys');
> var amqp = require('./amqp');
>
> var connection = amqp.createConnection({ host: 'localhost' });
>
> // Wait for connection to become established.
> connection.addListener('ready', function () {
> // Create a queue and bind to all messages.
> // Use the default 'amq.topic' exchange
> connection.publish("my-queue", {random_key:"this is my message"});
> connection.end();
> });
>
> [receiver - python/pika]
> #!/usr/bin/env python
> import pika
> import sys
>
> connection = pika.AsyncoreConnection(pika.ConnectionParameters(
> host='localhost'))
> channel = connection.channel()
>
> print ' [*] Waiting for messages. To exit press CTRL+C'
>
> def callback(ch, method, properties, body):
> print body,
> sys.stdout.flush()
> channel.basic_consume(callback,
> queue='my-queue',
> no_ack=True)
>
> pika.asyncore_loop()
This way around (presuming there's a restart in-between runs), node.js
sends to amq.topic, but nothing is bound there, so the message is discarded.
You might try binding the queue, in the Python, to the exchange
"amq.topic". You should probably also declare it.
If you actually don't want to use "amq.topic", and you probably don't if
you can help it, you might declare your own exchange and use that.
I'm not sure there's a way to send to the default exchange in node-amqp.
I fixed this, and some other things, in my fork, but it's a bit behind
the curve at the minute.
http://github.com/squaremo/node-amqp
> But nothing happens.
>
> Another thing (possibly related?) that I run into is if I create a queue
> in python using, e.g.:
>
> channel.queue_declare(queue='hello')
>
> Then, in node.js, when I do:
>
> var q = connection.queue('hello');
>
> I get this:
>
> Unhandled channel error: PRECONDITION_FAILED - parameters for queue
> 'hello' in vhost '/' not equivalent
>
> events:12
> throw arguments[1];
> ^
> Error: PRECONDITION_FAILED - parameters for queue 'hello' in vhost '/'
> not equivalent
> at Queue._onMethod
> (/Users/dtenenba/dev/dev-amqp/node-amqp/amqp.js:1390:15)
> at Connection._onMethod
> (/Users/dtenenba/dev/dev-amqp/node-amqp/amqp.js:784:28)
> at AMQPParser.onMethod
> (/Users/dtenenba/dev/dev-amqp/node-amqp/amqp.js:698:12)
> at AMQPParser._parseMethodFrame
> (/Users/dtenenba/dev/dev-amqp/node-amqp/amqp.js:415:10)
> at AMQPParser.execute
> (/Users/dtenenba/dev/dev-amqp/node-amqp/amqp.js:196:20)
> at Connection.<anonymous>
> (/Users/dtenenba/dev/dev-amqp/node-amqp/amqp.js:731:12)
> at Connection.emit (events:31:17)
> at IOWatcher.callback (net:489:16)
> at node.js:773:9
>
> It appears that python's idea of a 'hello' queue is different from that
> of node.amqp's. How can I do this so that I don't receive this error?
You can provide explicit values for the other parameters; that is (with
parameter names from memory ..),
[node.js]
var q = connection.queue("hello",
{ autoDelete: true, durable: false, exclusive: false });
[Python]
q = channel.queue_declare(queue='hello',
auto_delete=true,
durable=false,
exclusive=false)
I suspect the libraries differ only in the default value for
auto-delete, so supplying that may be enough.
> Hope this is the right place for this question. If not please tell me
> where I should post it.
This is a good place.
Regards,
Michael
More information about the rabbitmq-discuss
mailing list