RabbitMQ


Interoperation with Qpid

We have performed basic interoperability testing against Qpid's M1 release. So far, we have run

  • RabbitMQ's Java client against Qpid's M1 Java broker
  • Qpid's M1 Java client against RabbitMQ's Erlang broker
  • Qpid's Python test-suite against RabbitMQ's Erlang broker

Qpid Java client -> RabbitMQ broker

  • The Qpid clients do not currently call the "access.request" method, instead using a fixed ticket number of zero.

    RabbitMQ works around this by using a configurable "strict ticket checking" mode. By default this mode is disabled, which results in RabbitMQ fabricating suitable tickets on the fly, as if "access.request" had been invoked. This provides out-of-the-box interoperability between Qpid Java clients and RabbitMQ servers.

    To enable "strict" ticket checking, run the following command inside a RabbitMQ Erlang shell:

    rabbit_misc:set_config(strict_ticket_checking, enabled).

    To disable "strict" ticket checking, run

    rabbit_misc:set_config(strict_ticket_checking, disabled).

    Note that even when strict ticket checking is disabled, access control is still enforced. Hence users accounts must still be provisioned with suitable access rights to the appropriate virtual hosts and realms. Failure to do so will result in the Qpid client reporting "Unable to connect" or ACCESS_REFUSED errors, and RabbitMQ's log file will contain errors such as

    VHost access refused: no mapping for User <<"guest">>, VHost <<"/test">>
    ...
    Ticket fabrication for User <<"guest">>, VHost <<"/test">>, Realm "/data" failed: access_refused

    Use RabbitMQ's administration tool to provision user access, based on the information provided in the error messages.

  • The Qpid Java client does not properly handle negotiated maximum frame sizes of zero (meaning "unlimited").

    If the server presents a maximum frame size of zero during connection negotiation, subsequent attempts by the Qpid client to publish a message result in a "Error in client: java.lang.NegativeArraySizeException" error message.

    The RabbitMQ server works around this limitation by presenting a maximum frame size of 131072 octets during connection negotiation.

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

    The discrepancies are listed below. In most of these cases RabbitMQ has a dummy implementation in place for improved interoperability. The main exception are "headers" exchanges. An attempt to use them will result in the Qpid client reporting a COMMAND_INVALID error.

RabbitMQ Java client -> Qpid Java broker

  • The Qpid Java broker does not currently implement the "access.request" method, instead throwing an exception and closing the connection when that method is invoked.

    In order to make interoperability easier, the RabbitMQ Java client can be configured to suppress the sending of the "access.request" method and instead return a fixed ticket number of zero.

    To enable this behaviour, invoke the ConnectionParameters.setSuppressAccessRequest method, or set the com.rabbitmq.client.ConnectionParameters.suppressAccessRequest system property, which provides the default value for the former.

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

    One such case are "fanout" exchanges, which are implemented in RabbitMQ and used in several of the examples. Qpid will report an error "Unknown exchange type: fanout" in its logs and close the connection.

Test results from Qpid/Python Test Suite

The Qpid project is developing a broker-neutral test suite in Python. The following table details the results of running the AMQP 0-8 tests from that test suite against the RabbitMQ Erlang broker.

Note that the 0-8 spec file that comes with the test suite is different from the official spec. In order to run the tests you must download the official spec and run the test suite as follows:

run-tests -v -s specfile

Current Status Test Name Notes
ok test_example
invalid test_rollback The test assumes that delivered messages are requeued on rollback, which is in violation of the spec.
invalid test_auto_rollback The test is actually the same as test_rollback and is therefore invalid for the same reason.
ok test_commit
ok test_commit_overlapping_acks
ok test_ack
ok test_cancel
ok test_consume_exclusive
failing test_consume_no_local "no_local" planned but unimplemented
ok test_consume_queue_errors
ok test_consume_unique_consumers
ok test_get
failing test_qos_prefetch_count prefetch windowing planned but unimplemented
failing test_qos_prefetch_size prefetch windowing planned but unimplemented
ok test_recover_requeue
ok test
ok testDefaultExchange
failing testMatchAll "headers" exchanges are not part of AMQP 0-8
failing testMatchAny "headers" exchanges are not part of AMQP 0-8
ok testDifferentDeclaredType
ok testTypeNotKnown
ok testDirect
ok testFanout
failing testHeaders "headers" exchanges are not part of AMQP 0-8
ok testTopic
ok testAmqDirect
ok testAmqFanOut
failing testAmqMatch "headers" exchanges are not part of AMQP 0-8
ok testAmqTopic
ok test_amqp_basic_13
ok test_basic_delivery_immediate
ok test_basic_delivery_queued
ok test_closed_channel
ok test_invalid_channel
ok test_bind
ok test_declare_exclusive
ok test_declare_passive
ok test_delete_ifempty
ok test_delete_ifunused
ok test_delete_simple
ok test_purge
ok testAssertEmptyFail
ok testAssertEmptyPass
ok testMessageProperties