Messaging that just works
See also these other sources of information:
If you have a question not answered here, please join our mailing list or alternatively, contact us directly at info@rabbitmq.com.
Messaging describes the sending and receiving of data (in the form of messages) between systems. Messages are exchanged between programs or applications, similar to the way people communicate by email but with guarantees on delivery, speed, security and the absence of spam.
A messaging infrastructure (a.k.a. message-oriented middleware, a.k.a. enterprise service bus) makes it easier for developers to create complex applications by decoupling the individual program components. Rather than communicating directly, the messaging infrastructure facilitates the exchange of data between components. The components need know nothing about each other’s status, availability or implementation, which allows them to be distributed over heterogeneous platforms and turned off and on as required.
In adopting this architecture, the developer is insulated from the details of the various operating systems and network interfaces involved and the interoperability, scalability and flexibility of the application are improved.
Please see this presentation on Why you might need messaging for a general introduction or this page on Wikipedia for more information.
AMQP is a standard wire-level protocol and semantic framework for high performance enterprise messaging.
From the AMQP website:
AMQP is an Open Standard for Messaging Middleware.
By complying to the AMQP standard, middleware products written for different platforms and in different languages can send messages to one another. AMQP addresses the problem of transporting value-bearing messages across and between organisations in a timely manner.
AMQP enables complete interoperability for messaging middleware; both the networking protocol and the semantics of broker services are defined in AMQP.
For more information on what AMQP is, please see the AMQP Working Group's overview page.
AMQP is specifically designed with modern messaging needs in mind, including the reduction of change and maintenance costs through separation of integration concerns, removal of silo dependency, and freedom from language and platform lock in, without compromise on user experience, security, scalability and consistently excellent performance.
For more details please see this page.
RabbitMQ enables developers of messaging solutions to take advantage of not just AMQP but also one of the most proven systems on the planet. The Open Telecom Platform (OTP) is used by multiple telecommunications companies to manage switching exchanges for voice calls, VoIP and now video. These systems are designed to never go down and to handle truly vast user loads. And because the systems cannot be taken offline, they have to be very flexible, for instance it must be possible to 'hot deploy' features and fixes on the fly whilst managing a consistent user SLA.
Instead of creating a new messaging infrastructure, the RabbitMQ team selected the best one for the need, and built an AMQP layer on top. This combines the robustness and scalability of a proven platform with the flexibility of AMQP's messaging model.
The Open Telecom Platform (OTP) is a battle-tested library of management, monitoring, and support code for constructing extremely high-performance, reliable, scalable, available (nine nines!) distributed network applications. It is written in Erlang.
For good general introductions to both technological and business reasons supporting the use of Erlang and OTP, we recommend the following:
For further details on the rationale for choosing Erlang, please see the FAQ entries on clustering technology and management interfaces. Finally, we've prepared a comprehensive assessment of Erlang's advantages at this page.
AMQP is a very general system that can be configured to cover a great variety of messaging middleware use-cases. For example:
One of the simplest and most common scenarios is for a message producer to transmit a message addressed to a particular message consumer. AMQP covers this scenario by allowing queues to be named and to be bound to a "direct" exchange, which routes messages to queues by name.
In this scenario, the broadcasters publish messages to an AMQP "fanout" exchange, and subscribers create and subscribe to their own private AMQP queues, which forward published messages on to them, with one copy per queue.
Multicast is addressed at the broker implementation level. AMQP clients need not be made aware of transport-level optimisations such as multicast: broker clusters are free to use whatever such low-level optimisations are available from configuration to configuration.
Multiple optimisations are possible, since AMQP separates routing logic (exchanges and bindings) from message queueing (queues). Multicast relates only to routing from message publishers to message queues, and as a routing optimisation can be completely physically decoupled from AMQP's logical semantics. Further optimisations include physical separation of exchange from queue or even colocation of queue with a consumer application.
AMQP supports transactional publication, where an AMQP channel is opened, transactional mode is selected, messages are published and acknowledged, and the transaction is committed. The system guarantees atomicity and durability properties for transactional message activity.
Messages are individually flagged as transient or persistent in AMQP at the time of publication. By sending messages outside the transactional part of the protocol, in non-persistent mode, an application can achieve very high throughput and low latency.
Messages that are published in persistent mode are logged to disk for durability. If the server is restarted, the system ensures that received persistent messages are not lost. The transactional part of the protocol provides the final piece of the puzzle, by allowing the server to communicate its definite receipt of a set of published messages.
Store-and-forward is implemented by delivering messages marked as "persistent" to AMQP's durable queues. Published, persistent messages delivered to durable queues are stored on disk until a consumer retrieves and deletes them.
Because routing logic is decoupled from message delivery, RabbitMQ is able to support extended broker clustering across WANs. Some of the approaches include AJAX-style access to AMQP resources, and spanning-tree pseudo-multicast implemented internally to a RabbitMQ cluster.
The AMQP protocol, version 0-8, supports file
streaming by way of the file content
class. Very large files are transferred to a
temporary area on the broker before being routed
to queues for download by consumers.
A fanout exchange is the simplest exchange type, representing a 1:N message delivery pattern. No routing keys are involved – you simply bind a queue to the exchange and messages sent to that exchange get delivered to all the bound queues.
A direct exchange is a 1:1 form of communication where a routing key directs how a broker routes the message from the producer to the consumer. This is a straight match. If a queue binds to an exchange requesting messages with the routing key "lady", only messages labelled "lady" get delivered to that queue (not "lady.bird" or "lady.macbeth").
Here, the broker matches the routing key against a pattern to determine how to deliver the message. Instead of binding a queue to an exchange with a simple string, the queue is bound with a pattern. In the pattern, the symbol # matches one or more words and the symbol * matches any single word. Typical bindings might be "uk.#" for all items in the uk, "#.weather" for all weather items, or "uk.weather" for all uk weather items.
You would use some client to issue exchange.declare, which creates the exchange on the server when the server receives the command. You can do the exchange.declare at any time before you need to use the exchange.
The semantics of exchange.declare are that if the exchange does not already exist on the server, then create a new exchange. Otherwise reuse an existing exchange.
You may want to read the part in the spec about how the topic exchanges work. Using the example of nations which include sectors which include states which include regions which include counties, you could use topic exchange with 'nz.northisland.wellington.arovalley.arostreet. 54' and the bind with a pattern of nz.# or nz.southisland.#
Yep.
Direct exchanges can be simulated by using topic exchanges without wildcards, and fanout exchanges can be simulated by binding to topic exchanges with a full wildcard pattern.
The different kinds of exchange exist mainly for clarity's sake: it's easier for an observer looking at a system to see the intent behind the way it's configured. Secondarily, it opens up opportunities for optimising the less-general kinds of exchange.
Whether they disappear in time or not depends on the options that you set when you declare an exchange. One option is durability, which means an exchange will survive a server restart. Autodelete is another option that indicates that the server should remove an exchange when all queues have stopped using it.
Not wanting to be overly theoretical, but the AMQP working group is now moving to a more formal definition of declarations that mean that they have the same semantics as an assertion.
So by saying declare queue q or declare exchange x, you are effectively saying "I assert the existence of object o, if it does not exist, make it so".
Publishers need to write to somewhere.
Consumers need to have queues bound to something.
So both sides are only interested in the mere existence of the thing they need to do their job, not whether they or some other guy originally initiated that object's creation.
Semantically yes. But don't be too dogmatic about it in every scenario, if your application knows for sure that a particular queue or exchange definitely does exist, it can save a lookup for the existence of that object. Just an efficiency consideration. But don't optimize prematurely :-)
When you publish a message, you send a "routing key" along with it, that's used by the exchange when it decides which queues to forward a copy of the message on to. The links between exchanges and queues are created through binding, with a "binding pattern" that is used by the exchange when comparing against routing keys.
Routing keys (and so binding patterns) used with topic exchanges are dot.separated.strings.like.this.
Use "*" to match a single segment in the routing key: foo.*.zot will match foo.bar.zot, and foo.quux.zot, but not foo.bar.quux.zot.
Use "#" to match zero or more segments in the routing key: foo.#.zot will match all three of foo.bar.zot, foo.quux.zot, and foo.bar.quux.zot, as well as foo.zot.
You've got the pattern matching around the wrong way. The routing key must be absolute whilst the binding key can contain a wildcard. So "canada.*" is an opaque routing key. So to fix this, use "canada.*" as the binding key instead of "canada.sports" or "canada.politics".
Then create a separate binding for each thing that you are interested in.
Yes. See the previous FAQ.
Yes. RabbitMQ implements AMQP's "TX" message class, which provides atomicity and durability properties to those clients that request them.
Yes. RabbitMQ is built atop the industry-leading OTP Erlang libraries, which provides a solid foundation for building reliable software. The underlying system supporting the Rabbit codebase has been used by Ericsson to achieve nine nines (99.9999999%) of availability.
Yes. RabbitMQ brokers can be made up of an arbitrary number of nodes, each of which is available for AMQP clients to connect to and interact with. RabbitMQ's routing tables are shared across the entire cluster, and delivery of messages published at one node to a queue residing at another node is seamless. For details see the clustering guide. We are currently developing further support for live failover of AMQP resources within a cluster.
Yes. Erlang supports both single-node SMP configurations and configurations with multiple Erlang nodes running in a cluster within a single host.
Yes, RabbitMQ, and AMQP in general, supports store-and-forward-style exchanges and queues.
Absolutely. Some large telcos currently deploy Erlang/OTP-based systems in their SMSC infrastructure. At present these systems are not based on AMQP/RabbitMQ, but there is no reason why they couldn't be.
Yes. To begin with, Spring has good support for message access in Java: the RabbitMQ Java client is simply a POJO library. The same is true for other POJO-based systems, such as Mule. If you specifically wish to use JavaEE EJBs as message accessors, use a stateful session bean.
For frameworks in other languages, such as Ruby or in-browser Javascript, we plan on providing both RESTful HTTP access to AMQP features as well as AJAX- and web-services-style interfaces, allowing rapid development of web applications that take advantage of AMQP messaging.
Publication is an asynchronous activity - in other words, a message is "published" as soon it has left the client's TCP stack. The client has no knowledge of to whom the message is delivered. If you want some guarantees, you can use the mandatory and immediate flags on basic.publish, and you can also use transactional mode. In transactional mode, publishes are batched on the broker, until you issue a tx.commit. When you get the tx.commit-ok message back (i.e. commit is synchronous), you know the broker really has received the messages.
If a message is delivered to a consumer, and that consumer then dies (or closes the channel which has the subscription to the queue, or closes the connection itself) without acking the message, then RabbitMQ will reinject the message into the queue. If that same consumer then reconnects and creates a new subscription to the same queue, it's possible it'll receive the same message again. This is 'at least once' delivery and is very deliberate design to ensure that messages are not lost in transit.
The consumer can also call basic.recover which tells rabbit to resend all the messages sent to the consumer for which rabbit has not received an ack for. This basically amounts to the consumer saying "I know you sent me some messages, but I've forgotten what they are. Could you resend them all again?".
AMQP uses SASL (see also Wikipedia on SASL) for authentication of AMQP clients. Our current support for SASL is limited to the PLAIN authentication mechanism.
Authorization is implemented in RabbitMQ using a distributed database table mapping users to virtual hosts.
Message authentication, for instance using cryptographic message authentication codes, is not defined by the AMQP specification, but as for encryption, could be very easily implemented within the RabbitMQ client library.
RabbitMQ is developed on Debian Linux and Mac OS X. As the server component is written in Erlang, and the client component in Java, it is platform-neutral. Erlang runs on the following platforms (taken from Erlang's FAQ):
For those familiar with typical tiered session/application architectures such as JavaEE, it might help to think of the AMQP exchanges as corresponding to a logical session tier, and AMQP queues as corresponding to a logical application tier. From this point of view, RabbitMQ's routing tables can be seen as clustered shared session state. RabbitMQ uses the OTP distributed database, Mnesia, to reliably and persistently replicate session state across all nodes in a cluster.
RabbitMQ's current clustering mechanisms are built around Erlang's native support for reliable distributed programming. This is a deeply sophisticated framework, implemented at the language and virtual-machine level.
Some of the unique points about Erlang's networking and distribution model are:
Within an Erlang node cluster, Erlang's native high-speed messaging is used to provide an efficient way of distributing work across the cluster. Individual AMQP clients connect to machines within the cluster, and Erlang's distributed routing database routes AMQP messages to the appropriate endpoints.
For more detail on Erlang's benefits in an AMQP setting, please see this page.
Currently, AMQP durable queues and their persistent messages are recovered from disk at each server restart. Exchange failover is handled by OTP's support for clustering (see above).
Future releases will support live failover using, for
instance, a combination of the "known hosts" field in
connection.open-ok and the
connection.redirect message. Erlang's
built-in fault-tolerant database will ensure that
routing information is preserved, and the OTP supervisor
architecture in combination with AMQP's transactional
features will ensure that durable messages are not lost.
Like other messaging systems, AMQP and RabbitMQ provide internal addressing mechanisms based on notions such as routing keys, exchange addresses and queue names.
These are managed on a per-virtual-host basis. Please see the AMQP specification for details of the scoping of the various names in the network. We are actively investigating interoperation with other addressing schemes and systems.
At the core we are relying on Erlang/OTP to distribute one logical AMQP broker across several physical nodes, with the necessary broker state being maintained in an instance of OTP's distributed database Mnesia. There are certain aspects of the AMQP spec that are currently undergoing revision that impact this area, so watch out for associated new features and documentation in future releases of RabbitMQ.
No, the Rabbit server API is not designed for public consumption, but the contract that Rabbit obeys over time is AMQP.
We do, however, have API guides for
Also, please refer to the extensive server documentation which may contain the answer to your question.
Glad you asked. We've been working on a new persister since April (please see the mailing list or these slides for more).
The goal is to page messages to disk when necessary, politely block producers when absolutely necessary, and never ever crash. We should always be able to eventually accept a message.
Note that the current stable release (v1.7.0) (and all previous releases) is not very good in this regard and can easily explode due to holding too many messages in memory.
The main limitation is installed memory on the server (or, more accurately, the amount of per-process memory available on your platform).
However, it's not as simple as available RAM = maximum message size. This would only be possible if there was zero copying of a message from when it arrives at the machine until when it leaves. Its very likely that it will be copied several times.
We would be surprised if it's possible to push messages into RabbitMQ that are greater than 1/4 of the installed RAM. RabbitMQ tries to avoid using swap wherever possible and uses a configurable parameter to set a memory threshold above which producers are throttled.
Be aware that Windows imposes some "gotcha" constraints on per-process memory that have caught some people out in the past.
The next major release of RabbitMQ will include the new persister that (amongst other things) removes the current limitation that RabbitMQ holds all messages in memory all the time.
The persister will allow RabbitMQ to operate in a "zero RAM cost per message" mode where the volume of data that RabbitMQ can hold is limited solely by disk space.
However, even with the new persister, the fact remains that not only will the largest message need to fit in RAM (at some point) but it must also be able to be copied a few times. The change is simply that the existence of large messages in RAM does not preclude other large messages from arriving.
AMQP 0-8 included mention of a "stream" transfer class. However, no one implements it and it's gone in AMQP 0-9-1. It is the responsibility of applications to chunk large messages if they need to.
There are some client libs for doing 'file chunking'. Nanite is the one to look at if you are a Ruby developer.
It is not scheduled for any particular future version. It's likely it'll be addressed through some sort of active/active high-availability setup, but in general this is a very hard thing to try and do. Ultimately, the messages are going to have to exist on more than one node, and maybe written to disk on more than one node. This substantially complicates all sorts of semantics and guarantees of AMQP. Yes, we do plan to address this but it's very much a long term goal.
We maintain a list of clients, which is fairly complete. If you don't see one you want, please email our mailing list.
There are multiple ways for interacting with RabbitMQ in web messaging scenarios. For example, we provide broker plugins that expose a JSON/RPC endpoint from within the broker process. The community has contributed a set client libraries that allow AMQP communication for a variety of web platforms including actionscript and pubsubhubbub. A more complete list can be found under Web Messaging on the Get Started page.
The differences between 0-8, 0-9 and 0-91 are really small. The 0-91 version of the spec, which we support in dev (pre-release branch of our repo) has one major benefit: interoperability with OpenAMQ 0-91 and Qpid 0-91 in the main areas of behaviour (though note that OpenAMQ only partially implements AMQP). This is being tested now and you can expect more ‘noise’ about this in Q1 2010 in the community.
There is definitely no critical feature that 0-8 lacks but 0-91 has the merit of being shorter and tidying up lots of interoperability bugs. 0-9 has stuff in it that people did not like and this was removed in 0-91.
The AMQP 1-0 draft spec is still a work in progress and introduces some major changes from previous versions.
Our plan is to support 1-0 once it is finalised. As a matter of practicality we will offer a migration path, for example it will be possible to simulate 0-8 and 0-91 in 1-0. We do not expect 1-0 to be ready for serious implementation in the near term, and are satisfied that we are supporting the right versions with 0-8 and 0-91.
Don't panic! In the (unlikely) event that something goes wrong help is available. If you can't make sense of the error yourself then your first port of call should be our troubleshooting guide.
At the risk of sounding pedantic, you could wait for the dead node to recover from disk. In other words, RabbitMQ provides "eventual delivery" out of the box. If you want to persist more reliably than with a single disk then use a RAID or a SAN.
The problem with using a single node is the time it takes to recover the node and the cost (if any) of the client reconnection. The time to recover is partly influenced by how much state must be recovered and partly by the size of the unavailability window that your application can tolerate.
Many applications don't like to wait more than (say) 1ms, 10ms or 50ms before they can send their message. In this case, you will typically want to send a message _before_ the crashed node has been able to recover. You can achieve this in two ways:
A classic use-case for messaging systems is the example of subscribing to a topic of, say, 'market prices' for an asset. By that a client very often means, "send me the last published one and then subscribe me to any update". Sometimes it is not necessary if the asset is liquid (MSFT) but if it is illiquid, the client should receive the last available message, as it's possible there will be a long delay before the next update.
Does RabbitMQ support this?
This is not something AMQP provides out-of-the-box, although one can imagine a solution involving a trivial service (a simple hash table, in effect) answering requests for most-recent-price served via AMQP. The client would subscribe to the stream as usual, and in parallel ask the service for the most recent price.
Such a service could be implemented either inside the RabbitMQ broker, in Erlang, thus taking advantage of Erlang's distribution and high-availability properties, or it could be implemented outside the broker, as a regular AMQP client.
Mike Bridgen has created an experimental last value cache, implemented using RabbitMQ's plugin exchange type. It is available to download from github.
Say I want to transfer a message across the AMQP network, without depending on the target being there, and that the 'channel' between the message source client and the message target client should be strongly encrypted and authenticated. Is this something RabbitMQ provides?
There are two kinds of encryption that could be supported by an AMQP implementation.
The first is encryption of the AMQP stream. There's no provision in the standard for that, but it is possible to use SSL with RabbitMQ as of Release 1.7.0.
The second kind of encryption is encryption of individual messages. AMQP is silent on this front as well, but using a layer of encryption in the clients is very easy. Adding support for this to RabbitMQ's client library would be a simple matter.
RabbitMQ uses AMQP internally to the broker to notify interested parties of significant events. Administration and management exchanges are provided for tools to bind to.
Various management and monitoring tools are available from RabbitMQ and the community. Information about logging output can be found in the install guide.
There are several ways you can accomplish this depending on exactly what you want to achieve. From the command line, you can use "rabbitmqctl list_queues" to list the queues at a particular node and virtual host. The rabbitmqctl documentation has more information about the various options you can use with this command. Using AMQP, the 'queue.declare' command, which is idempotent, returns in one of the ' queue.declare-ok' fields the number of messages in the queue that are ready for delivery to consumers. The same information is also returned when fetching messages with 'basic.get', in a field of ' basic.get-ok'.
As a third alternative, if you have installed the RabbitMQ Status Plugin you can get queue depths (and lots more broker status information) over http.
RabbitMQ implements AMQP's TX message class to support atomic operations with clients that request them.
If you need only to acknowledge receipt of a message you should get the consumer to send a basic.ack once its done with processing. There's no need to use tx in this case.
However, if you need to both ack a message and publish some other messages as an atomic unit then you should set tx.select on the channel to start a transaction. When processing the received message, you can publish your messages and ack; only when you finally call tx.commit do the actions of the transaction take effect. In this case, if the consumer crashes, the ack and all publications get forgotten: either all of the actions happen or nothing happens.
If, at the application level, you realise that due to some external event everything needs to be cancelled then call tx.rollback on the channel.
You can test the RabbitMQ broker by:
Yes: you can either run your client against our public demonstration server, or download and run a server of your own to experiment with.
Since replication is used mainly to propagate routing table information between Erlang nodes within a cluster, it has a low impact on performance to begin with; also, it is trivial to arrange for a "queue-only" Erlang node to join the cluster, only able to consume from queues, which can then avoid being part of the routing-table replication system.
There's a very basic, very simple AMQP protocol analyzer in
class com.rabbitmq.tools.Tracer. Invoke it with
runjava.sh com.rabbitmq.tools.Tracer listenPort connectHost connectPort
There is also an AMQP plugin available for Wireshark .
Glad you asked – yes there is! LShift are hosting a demonstration RabbitMQ server that is freely available for people to try out, perhaps for testing interoperation or experimenting with WAN AMQP connections.
All supported RabbitMQ features are available on the server, including persistent storage. While we intend to keep the server running for long stretches, we will be tracking RabbitMQ development, so reserve the right to restart it, possibly erasing its database in the process from time to time.
Here are the connection details:
During debugging, you may wish to monitor the messages that are being sent through the amq.rabbitmq.log topic exchange. One way of doing this is to make use of the XMPP IM gateway we run on dev.rabbitmq.com, by adding amq.rabbitmq.log@dev.rabbitmq.com to your XMPP roster.
Rabbit uses mnesia to replicate information about a broker (excluding messages), so you may want to read the relevant sections about administration in the mnesia guide before doing anything. Don't just copy the data directory and hope that mnesia will just magically recover this, because it could well contain inode references. Also, taking Rabbit offline to do this may be a good idea.
There is also the issue of persistent messages, which are not stored in mnesia. This needs to handled separately.
And be aware that queue processes will not automatically be migrated.
And as always, if this is production data, then taking a backup is generally a prudent idea.
If you have done this already, then send a message to the list because I'd like to write more about this question, but don't have any time.
Yes it does! Many people have asked about this use case and we've devloped an implementation that we call Shovel. You can read more about Shovel on the LShift blog.
Please see the section on access control in the RabbitMQ admin guide.
RabbitMQ operates at sub-millisecond latency in transient mode under a load of 10k messages per second. In persistent mode, it should be possible to achieve a throughput of 3-5k messages per second stored to disk depending upon the exact configuration.
Please contact us if you would like more information relevant to your setup.
From our testing, we expect easily-achievable throughputs of 4000 persistent, non-transacted one-kilobyte messages per second (Intel Pentium D, 2.8GHz, dual core, gigabit ethernet) from a single RabbitMQ broker node writing to a single spindle.
Please let us know how RabbitMQ performs for you!
To disable transactionality, use an AMQP channel which
is not in "TX" mode (ie. do not call
tx.select). To disable message persistence,
set the "delivery mode" field in the
basic-class properties for the message to
either absent or to one, as mode two enables
persistence.
Based on typical OTP application scalability, we expect close-to-linear scaling.
It depends how and why it died, of course. Please differentiate between a dead machine and a partitioned network. One quick fix for a truly dead node may be to get a backup machine, reinstall the OS and Rabbit and then just restart Rabbit with the contents of the old mnesia data directory (if the disk is still ok, then you could just try slotting it in the new machine). Make sure that the backup machine has the same name as the machine that died. If this works, you are in luck. If not, i.e. mnesia does not seem to be recovering itself (it hangs will the waiting_for_tables error message), then what you can try is to nuke the mnesia directory and bring this node as part of the cluster and let it replicate itself from the other cluster members. Note that this will not restart queue processes that were running on this node before it crashed. But you can just re-declare the queues.
I know this is dependent on the number of messages to load, but is there any indication you can give (such as n seconds per GB, or n seconds per 1K messages...)?
It depends on the disk bandwidth as well. A million messages in a queue can take up to five minutes, although this is very much a worst case scenario and we're looking at ways of making this faster. For example, if know that RabbitMQ was shutdown safely then fewer checks are needed on recovery. At the moment, with the new persister, we're doing a very thorough fsck when we come back up. If we know that we've been shutdown safely then we don't need to do that. This is ongoing work.
State is only stored on disk if it must be recoverable. For durable queues / exchanges / bindings, we use mnesia. If mnesia is unable to start and read in the tables recording this information then RabbitMQ cannot start or recover those queues / exchanges / bindings.
With the new persister, RabbitMQ manages the storage of all message content on disk itself. The recovery routines for these are robust and do their best to recover as much as possible. If corruption occurs, RabbitMQ will recover what it can, and continue to start up normally.
Currently, the main reason that RabbitMQ might die is when it gets overwhelmed by messages and starved of RAM. The good news is that tith the new persister this is no longer a problem! Other than that, our users almost never report crashes. The Erlang / OTP platform is very stable, exhaustively battle-tested and extremely reliable.
Although we could do this, we don't, because it's too expensive. This would mean replicating every message across the network in a synchronous fashion. And not too many people really need it, in the event of a Rabbit node crashing, they just replay the log for that node.
BBHoss started a discussion about this on IRC (look for the discussion about HA and DR between BBHoss and hal).
Having said that, this may be a use case for pluggable queues, for the avail-o-nados out there :-)
There is no hard limit to the number of virtual hosts that can be configured within a RabbitMQ cluster, save available disk and memory resources.
Virtual hosts within AMQP are decoupled from the physical network layout: one virtual host can be accessed from multiple clustered brokers, just as many virtual hosts can be accessed within a single broker. Virtual hosts act solely as a namespacing mechanism for AMQP resources.
We want to get to the point where one can dynamically add and remove nodes to/from a cluster that represents one logical AMQP broker, for both reliability and scalability (to very high numbers of nodes).
This is an important area for us, and one of the reasons we chose Erlang/OTP as the implementation platform for RabbitMQ.
You mean concurrent TCP connections? In theory as many as the operating system will give you. If there are any niggles they can be sorted out quite easily.
Also note that AMQP allows you to multiplex AMQP sessions across a single TCP connection.
We are discussing testing, both functional and performance, within the AMQP working group, with the idea of defining a shared set of AMQP tests, and the code to implement them.
The problem is that there are many possible configurations of the test infrastructure, the RabbitMQ broker, the clients, and the tests themselves (e.g. AMQP supports many different forms of message delivery). In order to obtain meaningful performance figures one would have to specify exactly what the setup is, to the point where anybody can replicate it. Even then one would get just one data point in an infinite space of possible configurations, and it is generally impossible to extrapolate the results from one test to other scenarios.
The standard only defines basic username/password authentication. There are plans to extend that with SASL or some such mechanism.
It should be possible to add SSL/TLS quite trivially. Certificate management would be done in a similar fashion to most other SSL/TLS-enable apps.
The protocol is pure binary.
The short answer is that you have too many Erlang processes (i.e. lightweight processes, not Unix processes). The default system limit is 32767, so if you need more, start the Erlang VM with the +P flag to set the maximum number of allowed processes. RabbitMQ uses Erlang processes for each channel, for each connection, and for each queue within the broker. If you are running into the system limit, you might be running a large system, or you might be creating unnecessary resources.
Not at all. RabbitMQ is written to take advantage of multi-core CPUs; however, there are limitations. For example, a single queue is a single thread so if you are running with just one queue it's unlikely you'll utilise substantially more than one CPU core.
That said, there are node-wide threads within Rabbit, such as the persister, and every connection and every channel have their own threads. As a result, one queue with one producer sending persistent messages may well use up to, say, 2.5 cores, but it won't be possible to push that wider. As you add further queues, you will be able to use more CPU cores.
There are some. The most likely is the bandwidth to your hard disks: if you are sending lots of persistent messages, and they are going to disk, then the persister thread will rapidly become the bottleneck as it'll max out the bandwidth of your disk drives.
At that point, adding additional nodes, especially by scaling out to include additional machines, will be beneficial as you'll get another disk controller and more disks. If you're not doing any persistent messaging, then again, due to other per-node processes becoming bottlenecks, it will eventually (probably after tens of thousands of queues) become more beneficial to add additional machines and nodes rather than additional CPU cores to one machine.
High latency WANs will hurt performance for operations involving mnesia transactions. This pretty much amounts to any modification of topology: queue add/delete, exchange add/delete, binding add/delete. Publishes and get/consume are unaffected.
Topology change operations (see above) could potentially pause operation for a brief time but they will complete eventually. We use the net_kernel erlang module to do monitoring between nodes. The default "tick" time there is 60 seconds but this can be reduced. Further, in the event of a failure, any communication between the nodes will likely result in an error being generated and detected immediately: i.e. the only time at which you would not know about a node failure for 60 seconds is if there was no communication between the nodes for that amount of time.
In the event of a network brownout between two nodes in a cluster, the cluster will fail. At that point, each node is unable to see the queues on the other node. Thus messages will silently be dropped.
You can set the mandatory flag on basic.publish which will result in the publisher receiving an error message should the message be unable to be routed to a queue.
Replicated brokers allow you to do active/active HA setups. However, you have to manually ensure that the topology of the brokers is kept the same and you must manually do deduplification on the consumers. This is very much a RAID-1 style solution. Clusters, on the other hand, are closer to RAID-0 from the point of view of queues, but exchanges and bindings are replicated to every node in the cluster.
It's true that the composition of a cluster can be altered dynamically, however, a node must be "reset" before it can join a cluster. Resetting a node removes all queues / exchanges / bindings / messages from the node. When a node leaves a cluster it must also be reset before it can become a standalone node. If the node leaves a cluster due to all the other nodes dying, then it'll continue to operate with all the exchanges the cluster had, and the queues that were on the node. Bindings to those queues will be maintained.
Right. It's very basic. Nodes can respond to a client connection attempt with AMQP's connection.redirect method (unless the client supressed redirection by setting the insist flag in connection.open. Currently, we do this by looking at the load average of each node and picking the least loaded. This is not ideal and in some cases is suboptimal. For example, when the redirected client goes on to consume from a queue on a different node. We should point out that the redirect ability of AMQP disappears in 0-91 as it's really not the job of AMQP to be doing this.
RabbitMQ is free software in both the gratis and libre senses, licensed under the Mozilla Public License.
RabbitMQ is supported both commercially and as an open-source project. For general questions please join our mailing list or send us an email.
Follow the links to Services for information about commercial support.
RabbitMQ is distributed under the open-source Mozilla Public License.
If you would like to explore other licensing options, please get in touch with us by emailing info@rabbitmq.com.
Welcome aboard! We love contributions - here are some suggestions for what you can work on:
We're happy to hear from anyone who wants to get involved or is curious about how we intend to manage the project.
RabbitMQ is versioned with the scheme
major.minor.patch.
major: This number indicates the major
version of the software. It is only changed for
significant alterations to the software, such as (for
instance) a total rewrite.
minor: A change in this number indicates
new or significantly altered features.
patch: This number changes to make each
distinct packaging of the software uniquely
numbered. Small changes such as bug-fixes or packaging
alterations may cause a change in only the
patch number.
Please join our mailing list or send questions to info@rabbitmq.com. We'd love to hear from you.