In order to get the most out of a system, you need to know how to configure and control it. Depending on the type of system, these tasks could turn out to be quite daunting and onerous (consider a relational database, for example). However, the RabbitMQ team has provided very convenient facilities for administering and managing the message broker.
Topics covered in the chapter:
Administration of RabbitMQ server instances can be considered in several directions:
Some of the preceding concepts are covered in subsequent chapters. We already saw how easy it is to start/stop/restart instances using the rabbitmqctl
and rabbitmq-server
utilities that are part of the standard RabbitMQ installation. Before diving into the nuts and bolts of RabbitMQ administration, let's review the standard directory structure of a typical RabbitMQ server installation. In Windows, run the following command from the installation folder of RabbitMQ:
tree /A
The following screenshot displays the output from the preceding command:
Mnesia is a distributed NoSQL database used by RabbitMQ to store information about users, vhosts, exchanges, queues, bindings, index files (the position of messages in queues), and cluster information. It can store data either on RAM or on disk. Although persistent messages are stored along with the Mnesia files (in the Mnesia folder), they are not managed by Mnesia. RabbitMQ provides its own persistent storage for messages. On the one hand, persistent messages are stored in the msg_store_persistent
directory (both when they are persisted when received on a queue or when memory consumption grows beyond a specific threshold); on the other hand, non-persistent (transient) message are persisted in the msg_store_transient
directory (when memory consumption on a queue grows beyond a specific threshold).
The ebin
directory contains the Erlang compiled sources. They are cross-platform and are interpreted by the Erlang virtual machine installed on the machine on which the RabbitMQ server is installed.
The include
directory includes the Erlang header files (similar in notion to C++ header files but for Erlang).
The log
directory contains the RabbitMQ log files and the Erlang SASL (System Application Support Libraries) log files, not to be confused with SASL (Simple Authentication and Security Layer), for which RabbitMQ also provides support, covered in Chapter 9, Security. Erlang SASL provides support for topics such as error logging, alarm handling, and overload regulation.
The plugins
directory provides packages for the RabbitMQ binaries.
The sbin
directory contains the RabbitMQ scripts used for server administration, such as rabbitmq-server.bat and rabbitmqctl.bat under Windows.
The following screenshot illustrates the RabbitMQ folder structure for Ubuntu/Debian:
And the following is for a generic Unix installation:
Note that database and log files are not created until the RabbitMQ broker is started for the first time. If you delete the RabbitMQ database and/or log files, they will be recreated when the broker is started again.
The locations of some parts of the RabbitMQ installation files can be configured using environment variables, such as:
RABBITMQ_BASE
sets the location of the RabbitMQ database and log files. Note that, if it is not set under Windows, then the default location for the variable will be %APPDATA%RabbitMQ
(meaning that your database, log, and configuration files will be stored under that directory unless other configuration parameters are used to change their location). You can set this directory to be the installation folder of your RabbitMQ server if you want to store the database, log, and configuration in the same location as the other RabbitMQ server components.RABBITMQ_CONFIG_FILE
sets the location of the RabbitMQ configuration file (without the .config
extension of the file).RABBITMQ_LOG_BASE
specifies the base directory for storing RabbitMQ log files.For more information on the various environment variables related to the directory structure of the RabbitMQ server, you can refer to the RabbitMQ server documentation.
The various RabbitMQ components can be modified in any of the following ways:
rabbitmqctl
script (in the sbin
directory)So far, we have seen how to programmatically create queues, exchanges, and bindings. However, they can be pre-created in the broker so that the overhead of managing them from source code on the producer/consumer side is minimized. Moreover, we can also create users, vhosts, and policies using the management plugin or the rabbitmqctl utility. For some administrative tasks, you can use a command line utility (rabbitmqadmin) that comes with the RabbitMQ management plugin. In order to download it, navigate to http://localhost:1
5672/cli/
and save it to a proper location (for example, the sbin
directory of the RabbitMQ installation; make sure you save it with a .py
extension since it is a Python script, and ensure you have Python 3 installed before using the script). To view all available commands for the rabbitmqadmin.py script, you can issue the following from the command line:
rabbitmqadmin.py help rabbitmqadmin.py help subcommands
You can easily create new users from the command line. For example, if you want to create a user with the name sam
and the password d1v
, and a user jim
with the password tester
, you can issue the following commands:
rabbitmqctl add_user sam d1v rabbitmqctl add_user jim tester
The preceding users are regular (non-administrative) users and not assigned to any vhost. At that point, if you try to access the web management console you will receive a login failure. In order to make sam
an admin user you can issue the following command:
rabbitmqctl.bat set_user_tags jim administrator
Now jim
is able to administer the broker and login to the management console. The users still don't have access to any vhost (even the default one). If you navigate to the Admin
tab in the management console, you will see something like this:
The following command can be used to list all users in the broker instance:
rabbitmqctl.bat list_users
If you want to change the password for sam
to t1ster
, you can issue the following command:
rabbitmqctl.bat change_password jim t1ster
If you want to delete the user sam
, you can issue the following command:
rabbitmqctl.bat delete_user jim
You can also manage users from the RabbitMQ web management interface or the rabbitmqadmin.py
script. Let's make sam
an administrator:
rabbitmqctl.bat set_user_tags sam administrator
We have already mentioned that vhosts are used to logically separate a broker instance into multiple domains, each one with its own set of exchanges, queues, and bindings. The following example creates the chat
and events
vhost:
rabbitmqctl.bat add_vhost chat rabbitmqctl.bat add_vhost events
Note that it might be a better idea to name your vhosts hierarchically (meaning that chat becomes /chat and vhost becomes /vhost; any child vhosts can be added following the same pattern—for example, /chat/administrators
and /events/follow
).
If you navigate to the Admin
tab in the management console and click on Virtual Hosts, you will see something like this:
The following command can be used to list all virtual hosts in the broker instance:
rabbitmqctl.bat list_vhosts
You can use the following command to the delete the events
vhost:
rabbitmqctl.bat delete_vhost events
You can also manage vhosts from the RabbitMQ web management interface.
Now that we have seen how to create users and vhosts, we can assign permissions to particular users so that they are able to access particular vhosts (and all of the RabbitMQ components associated with that vhost). The following example grants configure, write, and read permissions to all resources in the chat
vhost to the user jim
:
rabbitmqctl.bat set_permissions –p chat jim ".*" ".*" ".*"
Note that in some cases under Windows, any of the rabbitmqctl commands may not be properly executed due to Erlang issues with encoding under Windows. In that case, you can also use the rabbitmqadmin.py
script as follows:
rabbitmqadmin.py declare permission vhost=chat user=sam configure=.* write=.* read=.*
As you can see, the configure, write, and read permissions can be regular expressions that match the names of the vhosts components that the user has access to. You can list all permissions in the broker with the following command:
rabbitmqctl.bat list_permissions
Alternatively, you can use the rabbitmqadmin.py
script for this purpose:
rabbitmqadmin.py list permissions
You can delete the permission given to the user sam
for the chat
vhost using the following command:
rabbitmqctl.bat clear_permissions -p chat sam
Alternatively you can use the rabbitmqadmin.py
script for this purpose:
rabbitmqadmin.py delete permission vhost=chat user=sam
If you omit the vhost from the preceding commands, you will clear all permissions assigned to the user sam
. You can also list all vhosts to which the user sam
is assigned with the following command:
rabbitmqadmin -u sam -p d1v list vhosts
You can create exchanges from the RabbitMQ management web interface or the rabbitmqadmin script. The following example creates the logs
fanout exchange in the default vhost:
rabbitmqadmin.py declare exchange name=logs type=fanout
The following example creates another fanout exchange with the name logs
in the chat
vhost (first we set permissions for the guest user to the vhost; otherwise, we have to specify a user that has administrator permissions for the vhost):
rabbitmqadmin.py declare permission vhost=chat user=guest configure=.* write=.* read=.*rabbitmqadmin.py declare -V chat exchange name=logs type=fanout
When declaring an exchange, you can specify additional properties such as exchange durability. To delete the logs
exchange from the chat
domain, you can issue:
rabbitmqadmin.py -V chat delete exchange name=logs
To list all exchanges in the chat
vhost, you can issue:
rabbitmqadmin.py -V chat list exchanges
To list all exchanges in the default vhost, you can issue:
rabbitmqadmin.py list exchanges
You can create queues from the RabbitMQ management web interface or the rabbitmqadmin
script. The following example creates the non-durable error_logs
queue in the default vhost:
rabbitmqadmin.py declare queue name=error_logs durable=false
The following example creates a queue with the same name in the chat
vhost:
rabbitmqadmin.py -V chat declare queue name=error_logs
To delete the error_logs
queue from the chat
vhost, you can issue the following:
rabbitmqadmin.py -V chat delete queue name=error_logs
To list all queues in the default domain, you can issue:
rabbitmqadmin.py list queues
Now that we have seen how straightforward it is to create exchanges and queues, let's see how to create bindings. The following creates a binding between the logs
fanout exchange we already created and the error_logs
queue in the default vhost:
rabbitmqadmin.py declare binding source=logs destination=error_logs
In order to test that the binding works, we can use the rabbitmqadmin
script to publish to the logs
exchange, then read from the error_logs
queue (here you can check if the message is successfully retrieved from the queue), and finally clear the error_logs
queue from any messages:
rabbitmqadmin.py publish exchange=logs routing_key= payload="new log" rabbitmqadmin.py get queue=error_logs rabbitmqadmin.py purge queue name=error_logs
Policies allow you to define (and change) certain properties of exchanges and queues at runtime. Since no more than one policy can be defined per exchange/queue, a policy can incorporate multiple settings at once. Let's consider the following scenarios:
In order to set the capacity of the error_logs
queue in the default ('/') vhost to 200,000 bytes, you can apply the following policy:
rabbitmqctl set_policy max-queue-len "error_logs" "{""max-length-bytes"" : 200000}" apply-to queue
You can also use the rabbitmqadmin.py script for this purpose:
rabbitmqadmin.py declare policy name=max-queue-len pattern=error_logs definition="{""max-length-bytes"":200000}" apply-to=queues
The following policy sets the maximum queue length in terms of messages (if you want to apply it you must first drop the previously created policy):
rabbitmqadmin.py declare policy name=max-queue-len pattern=error_logs definition="{""max-length"":200000}" apply-to=queues
Notice that instead of the name of the queue (error_logs
in that case), you can specify a pattern for the names of the queues to which the policy applies. This means that policies apply to queues that match the pattern and they are added after the policy is created. To delete the policy you can issue:
rabbitmqctl.bat clear_policy max-queue-len
Alternatively you can issue:
rabbitmqadmin.py delete policy name=max-queue-len
Note that the queue length might also be set from the client using the x-max-length
arguments passed to the arguments map in the declaration of a queue from the client.
In order to set the TTL (time-to-live) of the messages to all queues in the default vhost to three seconds, you can apply the following policy:
rabbitmqadmin.py declare policy name=ttl pattern=.* definition="{""message-ttl"":3000}" apply-to=queues
Note that the message TTL for the queue might also be set from the client using the x-message-ttl
arguments passed to the arguments map in the declaration of a queue from the client or on a per-message basis using the expiration
field set properly on the AMQP.BasicProperties
instance passed when publishing a message. You can also set expiration for the entire queue, which means that the queue will be automatically deleted after a certain period of idle time; this is particularly useful when a large number of queues is created and they need to be purged over time. The following example sets the queue TTL for all queues starting with the response
prefix to 10 minutes:
rabbitmqadmin.py declare policy name=queue-ttl pattern=response.* definition="{""expires"":600000}" apply-to=queues
Note that the queue TTL might also be set from the client using the x-queue
arguments passed to the arguments map in the declaration of a queue from the client.
If a message TTL expires, the queue capacity is exhausted, or a message received from a queue is explicitly rejected from a consumer, it can be routed to an alternative dead-letter exchange. The following diagram provides an overview of the scenario:
The following example creates the logs_dlx
exchange and sets it as a dead-letter exchange to the error_logs
queue:
rabbitmqadmin.py declare exchange name=logs_dlx type=fanoutrabbitmqadmin.py declare policy name=ttl pattern="^error_logs$" definition="{""dead-letter-exchange"": ""logs_dlx"", ""message-ttl"":3000}" apply-to=queues
Note that if we use only "error_logs"
instead of "^error_logs$"
then error_logs_dlx
will also be matched and we don't want this to happen. Notice that in the preceding example we combined the dead-letter-exchange policy with the message-ttl policy. You can list all policies with the following command:
rabbitmqadmin.py list policies
Note that you have to make sure that only one policy applies at a time on a queue; if two or more patterns match a queue name then it becomes unclear which policy will be applied. If that happens, remove policies that apply to a queue and combine them in a single composite policy. To delete the max-queue-len
policy we created earlier, issue the following command:
rabbitmqadmin.py delete policy name=max-queue-len
In order to test that the dead-letter exchange is properly configured we can use the following scenario:
error_logs_dlx
that binds to the logs_dlx
exchangelogs
exchangeerror_logs_dlx
error_logs_dlx
queueThe following example can be used to test the preceding scenario:
rabbitmqadmin.py declare queue name=error_logs_dlx rabbitmqadmin.py declare binding source=logs_dlx destination=error_logs_dlx rabbitmqadmin.py publish exchange=logs routing_key= payload="dlx message"
Wait at least three seconds and execute the following in order to verify that the message is sent to the dead-letter queue (clearing the queue at the end):
rabbitmqadmin.py get queue=error_logs_dlx rabbitmqadmin.py purge queue name=error_logs
The RabbitMQ database stores both message server metadata and messages from queues. In the next sections we will see how can we manage this database for the purpose of disaster recovery.
As we have already seen, RabbitMQ uses Mnesia to store information about the various components of the broker as well as cluster configuration and a custom database for storing persistent messages. In that regard it is straightforward to back up the contents of the RabbitMQ database:
The restore procedure, as you might have guessed, is pretty similar. You should also consider the fact that if a message is not persistent it may not be backed up using the preceding procedure since it is not written to the persistent store of RabbitMQ (in the event of a crash). In order for a message to be persistent, the exchange and queue through which it passes must be durable (marked as such during creation) and the message must be marked as persistent (with a delivery mode set to 2 from the sender). A response for a successfully received persistent message is not sent until a message is written to the persistent log file on an exchange. You may be wondering about the case when a live backup must be made on the RabbitMQ database with preservation of messages at a particular point in time. In this case you have a number of options to consider, such as:
In many cases however you may need to backup/restore only the configuration of RabbitMQ components at a particular point in time.
In order to back up the RabbitMQ broker metadata (the configuration of broker components) you can use the rabbitmqadmin management plugin as follows (assuming we want to backup the broker configuration to a file named broker.export
in the current directory):
rabbitmqadmin.py export broker.json
If you open the file you will notice that there is a section for each type of component, along with the version of the broker:
{ "rabbit_version":"3.4.4", "users":[ { "name":"sam", "password_hash":"y7CFOccmv5tReRwEskXapNOSsmM=", "tags":"administrator" }, …. ], "vhosts":[ { "name":"chat" }, { "name":"/" } ], … }
To import back the configuration, you can use the following command:
rabbitmqadmin.py import broker.json
Note that it is a good idea to add a user-readable timestamp to the name of the export file, based on the utilities provided by your OS for that purpose. You can also perform the export/import of the current RabbitMQ configuration for the management web interface from the Overview tab.
3.147.71.94