Interoperability

Interoperation with Qpid

We have performed basic interoperability testing against Qpid's 0.6 release. So far, we have tested:

  • Qpid's 0.6 clients against the RabbitMQ broker
  • the RabbitMQ clients against Qpid's 0.6 Java broker
  • Qpid's Python test-suite against the RabbitMQ broker

Qpid clients » RabbitMQ broker

The 0.6 release of the Qpid java client was shipped with a bug that prevents it from correctly negotiating the protocol version. As it defaults to AMQP 0-10, it is unable to connect to any 0-8 or 0-9-1 broker (including RabbitMQ).

A solution is to use git revision 6f5d963, committed shortly after the main release which fixes protocol negotiation.

In order to run their examples, one must first configure the RabbitMQ broker with the necessary vhost (/test) and permissions(.* .* .*). This is most easily done through the management tools (rabbitmqctl).

Due to a disagreement regarding the spec, almost none of the examples will work. RabbitMQ declares the standard amq.* exchanges as durable. Before using them, Qpid always re-declares them, and does so as non-durable. As a result, RabbitMQ will raise a precondition failed exception for most of the examples.

As the tests below show, the Python client interoperates with the RabbitMQ broker completely -- the only incompatibilities are in the interpretation of AMQP. A slight difficulty lies in that the Python client has different APIs for AMQP 0-8/0-9/0-9-1 and 0-10. In order to work with RabbitMQ, the former should be used.

Both the Qpid Ruby client and the .NET client can connect to the RabbitMQ broker, but since both clients use 0-9-1 methods for 0-8 connections and since both clients default to 0-8, framing errors occur and the broker closes the connection. This problem might go away if the clients were somehow forced to use 0-9-1.

RabbitMQ clients » Qpid Java broker

Broadly speaking, the RabbitMQ clients can interoperate with Qpid. Exceptions to this rule are documented below.

Some of the RabbitMQ Java client tests and examples use features that are not implemented (correctly) in Qpid.

  • Qpid does not support the if-unused parameter of exchange.delete.
  • Qpid does not support auto-deleted and alternate exchanges.
  • Qpid misinterprets empty strings in the type field of passive exchange.declare methods; it will raise an exception in these circumstances. As a result, the exchangeDeclarePassive methods in the RabbitMQ clients will not work.
  • There are some differences in transaction semantics; Qpid is generally more lax and does not raise exceptions in certain circumstances.
  • There are some minor differences in qos semantics.

Furthermore, the Qpid Java broker does not accept "/" for a virtual host. Since this is the default value for all RabbitMQ clients, care must be taken to specify a different one before attempting to connect to Qpid.

The .NET and Erlang clients can connect to the Qpid broker. We have not done more in-depth testing.

Qpid C++ broker

The 0.6 Qpid C++ broker supports only AMQP 0-10; none of the RabbitMQ clients can connect to it.

Test results from Qpid/Python Test Suite

The Qpid project maintains a Python test-suite that aims to be mostly broker independent. It can currently be found in the python/ directory of their source distribution. To run the test suite, execute the following command in the aforementioned directory:

% python2.5 ./qpid-python-test -m tests_0-9 -m tests_0-8

The following table details the results of running the 0-8 and 0-9 tests against the RabbitMQ broker.

Current StatusTest NameNotes
oktests_0-8.basic.BasicTests.test_ack
oktests_0-8.basic.BasicTests.test_cancel
oktests_0-8.basic.BasicTests.test_consume_exclusive
plannedtests_0-8.basic.BasicTests.test_consume_no_local RabbitMQ does not support basic.consume{no-local}.
invalidtests_0-8.basic.BasicTests.test_consume_queue_errors Error codes changed for 0-9-1
oktests_0-8.basic.BasicTests.test_consume_unique_consumers
oktests_0-8.basic.BasicTests.test_get
oktests_0-8.basic.BasicTests.test_qos_prefetch_count
plannedtests_0-8.basic.BasicTests.test_qos_prefetch_size RabbitMQ does not support basic.qos{prefetch-size}.
oktests_0-8.basic.BasicTests.test_recover_requeue
oktests_0-8.broker.BrokerTests.test_ack_and_no_ack
failingtests_0-8.broker.BrokerTests.test_basic_delivery_immediate RabbitMQ does not support the basic.publish 'immediate' flag.
oktests_0-8.broker.BrokerTests.test_basic_delivery_queued
oktests_0-8.broker.BrokerTests.test_channel_flow
oktests_0-8.broker.BrokerTests.test_closed_channel
oktests_0-8.broker.BrokerTests.test_invalid_channel
oktests_0-8.example.ExampleTest.test_example
oktests_0-8.exchange.DeclareMethodOkiveFieldNotFoundRuleTests.test
oktests_0-8.exchange.DefaultExchangeRuleTests.testDefaultExchange
oktests_0-8.exchange.HeadersExchangeTests.testMatchAll
oktests_0-8.exchange.HeadersExchangeTests.testMatchAny
invalidtests_0-8.exchange.MiscellaneousErrorsTests.testDifferentDeclaredType Error codes changed for 0-9-1
oktests_0-8.exchange.MiscellaneousErrorsTests.testTypeNotKnown
oktests_0-8.exchange.RecommendedTypesRuleTests.testDirect
oktests_0-8.exchange.RecommendedTypesRuleTests.testFanout
oktests_0-8.exchange.RecommendedTypesRuleTests.testHeaders
oktests_0-8.exchange.RecommendedTypesRuleTests.testTopic
oktests_0-8.exchange.RequiredInstancesRuleTests.testAmqDirect
oktests_0-8.exchange.RequiredInstancesRuleTests.testAmqFanOut
oktests_0-8.exchange.RequiredInstancesRuleTests.testAmqMatch
oktests_0-8.exchange.RequiredInstancesRuleTests.testAmqTopic
oktests_0-8.queue.QueueTests.test_bind
oktests_0-8.queue.QueueTests.test_declare_exclusive
oktests_0-8.queue.QueueTests.test_declare_okive
oktests_0-8.queue.QueueTests.test_delete_ifempty
oktests_0-8.queue.QueueTests.test_delete_ifunused
oktests_0-8.queue.QueueTests.test_delete_simple
invalidtests_0-8.queue.QueueTests.test_purge Error codes changed for 0-9-1.
oktests_0-8.testlib.TestBaseTest.testAssertEmptyFailing
oktests_0-8.testlib.TestBaseTest.testAssertEmptyPass
oktests_0-8.testlib.TestBaseTest.testMessageProperties
invalidtests_0-8.tx.TxTests.test_rollback The test assumes that delivered messages are re-queued on rollback, which is in violation of the spec.
invalidtests_0-8.tx.TxTests.test_auto_rollback The test is actually the same as test_rollback and is therefore invalid for the same reason.
oktests_0-8.tx.TxTests.test_commit
oktests_0-8.tx.TxTests.test_commit_overlapping_acks
invalidtests_0-9.query.QueryTests.* Qpid specific extension.

Interoperation with OpenAMQ

OpenAMQ brokers

We have performed basic interoperability testing against the OpenAMQ/1.3d0 and OpenAMQ/1.4c0 brokers. We have run our Java client tests and examples against them.

Unfortunately, we found that the OpenAMQ brokers do not implement (correctly) a large part of the AMQP specification. As a result, they fail a large number of our tests. More precisely, we found that OpenAMQ:

  • does not support durable queues,
  • does not support multiple channels per connection,
  • does not encode queue.unbind methods correctly,
  • misinterprets the type field for exchange methods, and
  • does not appear to support transactions

Some of our examples, most notably MulticastMain, do work, so it is possible to do basic publish/consume. Note that the OpenAMQ brokers occasionally reset the connection without warning.

OpenAMQ PAL Examples

The OpenAMQ project has a small number of PAL scripts designed to test AMQP brokers.

These are short scripts that are compiled to C programs that use the OpenAMQ WireAPI. When running the examples, we found that it is useful to set the trace level to 1 (-t 1).

RabbitMQ passes most of the tests; the only incompatibilities we found are:

  • In addition to amq.topic, OpenAMQ implements an amq.regexp exchange.
  • OpenAMQ appears to add an extra 0 at the end of queue.unbind methods. This breaks RabbitMQ's frame decoding and causes the broker to close the connection.
  • RabbitMQ does not support the no-local parameter of basic.consume.
  • There are some slight disagreements as to what exception codes should be used in what situations.

RabbitMQ versions tested

The following versions of the RabbitMQ broker and clients were used when performing the tests:

RabbitMQ broker2.0.0
RabbitMQ Java Client2.0.0
RabbitMQ Erlang Client2.0.0
RabbitMQ .NET Client2.0.0