Virtual Hosts
Introduction
RabbitMQ is multi-tenant system: connections, exchanges, queues, bindings, user permissions, policies and some other things belong to virtual hosts, logical groups of entities. If you are familiar with virtual hosts in Apache or server blocks in Nginx, the idea is similar.
There is, however, one important difference: virtual hosts in Apache are defined
in the configuration file; that's not the case with RabbitMQ: virtual hosts are
created and deleted using rabbitmqctl
or the HTTP API instead.
Logical and Physical Separation
Virtual hosts provide logical grouping and separation of resources. Separation of physical resources is not a goal of virtual hosts, although certain resources can be limited for individual virtual hosts.
For example, resource permissions in RabbitMQ are scoped per virtual host. A user doesn't have global permissions, only permissions in one or more virtual hosts. User tags can be considered global permissions but they are an exception to the rule.
Therefore when talking about user permissions it is very important to clarify what virtual host(s) they apply to.
Virtual Hosts and Client Connections
A virtual host has a name. When an AMQP 0-9-1 client connects to RabbitMQ, it specifies a vhost name to connect to. If authentication succeeds and the username provided was granted permissions to the vhost, connection is established.
Connections to a vhost can only operate on exchanges, queues, bindings, and so on in that vhost. "Interconnection" of e.g. a queue and an exchange in different vhosts is only possible when an application connects to two vhosts at the same time. For example, an application can consume from one vhost then republishes into the other. This scenario can involve vhosts in different clusters or the same cluster (or a single node). RabbitMQ Shovel plugin is one example of such application.
Creating a Virtual Host
A virtual host can be created using CLI tools or an HTTP API endpoint.
A newly created vhost will have a default set of exchanges but no other entities and no user permissions. For a user to be able to connect and use the virtual host, permissions to it must be granted to every user that will use the vhost, e.g. using rabbitmqctl set_permissions.
Using CLI Tools
A virtual host can be created using rabbitmqctl's add_vhost
command
which accepts virtual host name as the only mandatory argument.
Here's an example that creates a virtual host named qa1
:
rabbitmqctl add_vhost qa1
Using HTTP API
A virtual host can be created using the PUT /api/vhosts/{name}
HTTP API endpoint
where {name}
is the name of the virtual host
Here's an example that uses curl to create a virtual host vh1
by contacting
a node at rabbitmq.local:15672
:
curl -u userename:pa$sw0rD -X PUT http://rabbitmq.local:15672/api/vhosts/vh1
Bulk Creation and Pre-provisioning
Virtual host creation involves a blocking cluster-wide transaction. Each node has to perform a number of setup steps which are moderately expensive. In practice it can take up to a few seconds for a virtual host to be created.
When a number of virtual hosts is created in a loop, CLI and HTTP API clients can outpace the actual rate of virtual host creation and experience timeouts. If that's the case operation timeout should be increased and delays should be introduced between operations.
Definition export and import is the recommended way of pre-configuring many virtual hosts at deployment time.
Virtual Host Metadata
Virtual hosts can have metadata associated with them:
- A description
- A set of tags
- Default queue type configured for the virtual host
All these settings are optional. They can be provided at virtual host creation time or updated later.
Using CLI Tools
The rabbitmqctl add_vhost
command accepts a virtual host name as well as a number of optional flags.
Here's an example that creates a virtual host named qa1
with quorum queues for default queue type,
a description and two tags:
rabbitmqctl add_vhost qa1 --description "QA env 1" --default-queue-type quorum
rabbitmqctl update_vhost_metadata
can be used to update all or some of the metadata values
demonstrated above:
rabbitmqctl update_vhost_metadata qa1 --description "QA environment for issue 1662" --default-queue-type quorum --tags qa,project-a,qa-1662
To inspect virtual host metadata, use rabbitmqctl list_vhosts
and provide the additional column(s):
rabbitmqctl -q --formatter=pretty_table list_vhosts name description tags default_queue_type
Using HTTP API
The PUT /api/vhosts/{name}
HTTP API endpoint
accepts a number of optional keys.
Here's an example that uses curl to create a virtual host qa1
by contacting
a node at rabbitmq.local:15672
. Quorum queues will be used for default queue type,
a description and two tags:
curl -u userename:pa$sw0rD -X PUT http://rabbitmq.local:15672/api/vhosts/qa1 \
-H "content-type: application/json" \
--data-raw '{"description": "QA environment 1", "tags": "qa,project-a", "default_queue_type": "quorum"}'
can be used to update all or some of the metadata values demonstrated above:
curl -u userename:pa$sw0rD -X PUT http://rabbitmq.local:15672/api/vhosts/qa1 \
-H "content-type: application/json" \
--data-raw '{"description": "QA environment for issue 1662", "tags": "qa,project-a,qa-1662", "default_queue_type": "quorum"}'
Virtual host metadata is returned by the GET /api/vhosts/{name}
endpoint:
curl -u userename:pa$sw0rD -X GET http://rabbitmq.local:15672/api/vhosts/qa1
Default Queue Type (DQT)
When a client declares a queue without explicitly specifying its type using the x-queue-type
header,
a configurable default type is used. The default can be overridden by specifying it in virtual host metadata (see above):
rabbitmqctl add_vhost qa1 --description "QA environment 1" --default-queue-type quorum --tags qa,project-a
Supported queue types are:
- "quorum"
- "stream"
- "classic"
The default is only effective for new queue declarations; updating the default will not affect queue type of any existing queues or streams because queue type is immutable and cannot be changed after declaration.
Starting with RabbitMQ 3.13.4
, for queues that were declared without an explicitly set
queue type, the effective virtual host default will be injected into the queue properties
at definition export time.
Node-wide Default Queue Type (Node-wide DQT)
Starting with RabbitMQ 3.13.4
, instead of configuring the same default queue type for every virtual host
in the cluster, a node-wide default can be set using rabbitmq.conf
:
# supported values are: quorum, stream, classic, or a custom queue type module name
default_queue_type = quorum
When both the virtual host DQT and the node-wide DQT are set, the virtual host one will take precedence.
Migration to Quorum Queues: a Way to Relax Queue Property Equivalence Checks
Queue property equivalence check for queue type can be relaxed
using a boolean setting, quorum_queue.property_equivalence.relaxed_checks_on_redeclaration
,
makes it possible to relax queue property equivalence checks
for quorum queues.
Specifically, when a quorum queue is redeclared and the client-provided type is set to "classic", this setting will help avoid a channel exception, making it easier to migrate to quorum queues step by step, without upgrading all applications in a short period of time.
# this setting is meant to be used during transitionary periods when
# RabbitMQ default queue type is changed but not all applications have been
# updated yet
quorum_queue.property_equivalence.relaxed_checks_on_redeclaration = true
Deleting a Virtual Host
A virtual host can be deleted using CLI tools or an HTTP API endpoint.
Deleting a virtual host will permanently delete all entities (queues, exchanges, bindings, policies, permissions, etc) in it.
Using CLI Tools
A virtual host can be deleted using rabbitmqctl's delete_vhost
command
which accepts virtual host name as the only mandatory argument.
Here's an example that deletes a virtual host named qa1
:
rabbitmqctl delete_vhost qa1
Using HTTP API
A virtual host can be deleted using the DELETE /api/vhosts/{name}
HTTP API endpoint
where {name}
is the name of the virtual host
Here's an example that uses curl to delete a virtual host vh1
by contacting
a node at rabbitmq.local:15672
:
curl -u userename:pa$sw0rD -X DELETE http://rabbitmq.local:15672/api/vhosts/vh1
Limits
In some cases it is desirable to limit the maximum allowed number of queues or concurrent client connections in a vhost. As of RabbitMQ 3.7.0, this is possible via per-vhost limits.
These limits can be configured using rabbitmqctl
or HTTP API.
Configuring Limits Using rabbitmqctl
rabbitmqctl set_vhost_limits
is the command used to define vhost limits.
It requires a vhost parameter and a JSON document of limit definitions.
Configuring Max Connection Limit
To limit the total number of concurrent client connections in vhost
vhost_name
, use the following limit definition:
rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": 256}'
To block client connections to a vhost, set the limit to a zero:
rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": 0}'
To lift the limit, set it to a negative value:
rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": -1}'
Configuring Max Number of Queues
To limit the total number of queues in vhost
vhost_name
, use the following limit definition:
rabbitmqctl set_vhost_limits -p vhost_name '{"max-queues": 1024}'
To lift the limit, set it to a negative value:
rabbitmqctl set_vhost_limits -p vhost_name '{"max-queues": -1}'
Virtual Hosts and STOMP
Like AMQP 0-9-1, STOMP includes the concept of virtual hosts. See the STOMP guide for details.
Virtual Hosts and MQTT
Unlike AMQP 0-9-1 and STOMP, MQTT doesn't have the concept of virtual hosts. MQTT connections use a single RabbitMQ host by default. There are MQTT-specific convention and features that make it possible for clients to connect to a specific vhosts without any client library modifications. See the MQTT guide for details.