多租户与权限
每一个RabbitMQ服务器都能创建虚拟的消息服务器,称为虚拟主机(virtual host),每一个vhost本质上都是独立的小型RabbitMQ服务器,拥有自己独立的队列、交换机及绑定关系等,并且它拥有自己独立的权限。
vhost是AMQP概念的基础,客户端在连接的时候必须制定一个vhost。RabbitMQ默认创建的vhost是‘/’,默认的用户名guest和密码guest就可以访问它。
创建新的虚拟主机:
1 | ~]# rabbitmqctl add_vhost vhost1 |
2 | Creating vhost "vhost1" ... |
3 | ...done. |
4 | ~]# rabbitmqctl list_vhosts |
5 | Listing vhosts ... |
6 | / |
7 | vhost1 |
8 | ...done. |
9 | ~]# rabbitmqctl delete_vhost vhost1 |
10 | Deleting vhost "vhost1" ... |
11 | ...done. |
在rabbitmq中,权限控制权则是以vhost为单位的。当创建一个用户时,用户通常会被指排给至少一个vhost,并且只能访问被指派的vhost内的队列,交换机和绑定关系。
相关的授予权限命令为:
rabbitmqctl set_permissions [-p vhost] {user} {conf}{write}{read}
- vhost: 授予用户访问权限的vhost名称,可以设置为默认值,即vhost为‘/’
- user: 可以访问指定vhost的用户
- conf: 一个用于匹配用户在哪些资源上拥有可配置的正则表达式
- write: 一个用于匹配用户在哪些资源上拥有可写权限的正则表达式
- read: 一个用于匹配用户在哪些资源上拥有可读权限的正则表达式
注:可匹配指的是队列和交换机的创建及删除之类的操作,可写指的是发布消息,可读指与消息有关的操作,包括读取消息及清空整个队列等。
1 | ~]# rabbitmqctl add_user root toor |
2 | Creating user "root" ... |
3 | ...done. |
4 | ~]# rabbitmqctl set_permissions -p vhost1 root ".*" ".*" ".*" |
5 | Setting permissions for user "root" in vhost "vhost1" ... |
6 | ...done. |
7 | ~]# rabbitmqctl list_permissions -p vhost1 |
8 | Listing permissions in vhost "vhost1" ... |
9 | root .* .* .* |
10 | ...done. |
11 | ~]# rabbitmqctl list_user_permissions root |
12 | Listing permissions for user "root" ... |
13 | vhost1 .* .* .* |
14 | ...done. |
15 | ~]# rabbitmqctl clear_permissions -p vhost1 root |
16 | Clearing permissions for user "root" in vhost "vhost1" ... |
17 | ...done. |
用户管理
在RabbitMQ中,用户是访问控制的基本单元,且单个用户可以跨越多个vhost进行授权。针对一个至多个vhost,用户可以被赋予不同级别的访问权限,并使用标准的用户名和密码来认证用户。
创建用户:
rabbitmqctl add_user {username} {password}
修改密码:
rabbitmqctl change_password {username} {newpassword}
清除密码:
rabbitmqctl clear_password {username}
删除用户:
rabbitmqctl delete_user {username}
查看用户:
rabbitmqctl list_users
设置用户的角色:
rabbitmqctl set_user_tags {username} {tag}
用户的角色分为5种类型:
- none: 无任何角色,新建的用户的角色默认为none
- management: 可以访问web管理页面
- policymarker: 包含management的所以权限,并且可以管理策略和参数
- monitoring: 包含management的所以的权限,并且可以看到所有连接、信道及节点相关的信息
- administrator: 包含monitoring的所有权限,并且可以管理用户、虚拟主机、权限、策略、参数等,代表最高权限。
注意:tag参数用于设置0个、1个或者多个角色,设置之后任何之前现有的身份都会被删除。
web端管理
我们可以使用rabbitmqctl工具来管理rabbitmq,但是为了能够运行rabbitmqctl工具,当前用户需要拥有访问erlang cookie的权限,由于服务器是以guest或者root用户身份运行的,因此需要获得这些文件的访问权限,这样就会引申出权限管理的问题。
rabbitmqctl [-n node] [-t timeout] [-q] {command} {command opotions…}
注意:节点不运行,因不可达或不匹配的Erlang cookie而拒绝连接
RabbitMQ management插件可以提供web管理界面用来管理如前面所述的虚拟主机、用户等,也可以用来管理队列、交换机、绑定关系、策略、参数等,还可以用来监控RabbitMQ服务的状态及一些数据统计类信息。启用插件使用rabbitmq-plugin:
rabbitmq-plugins [-n node] {command} {command opotions…}
- 启用插件:rabbitmq-plugins enable [plugin-name]
- 关闭插件:rabbitmq-plugins disable [plugin-name]
1 | ~]# rabbitmq-plugins list |
2 | [e] amqp_client 3.3.5 |
3 | [ ] cowboy 0.5.0-rmq3.3.5-git4b93c2d |
4 | [ ] eldap 3.3.5-gite309de4 |
5 | [e] mochiweb 2.7.0-rmq3.3.5-git680dba8 |
6 | [ ] rabbitmq_amqp1_0 3.3.5 |
7 | [ ] rabbitmq_auth_backend_ldap 3.3.5 |
8 | [ ] rabbitmq_auth_mechanism_ssl 3.3.5 |
9 | [ ] rabbitmq_consistent_hash_exchange 3.3.5 |
10 | [ ] rabbitmq_federation 3.3.5 |
11 | [ ] rabbitmq_federation_management 3.3.5 |
12 | [E] rabbitmq_management 3.3.5 |
13 | [e] rabbitmq_management_agent 3.3.5 |
14 | [ ] rabbitmq_management_visualiser 3.3.5 |
15 | [ ] rabbitmq_mqtt 3.3.5 |
16 | [ ] rabbitmq_shovel 3.3.5 |
17 | [ ] rabbitmq_shovel_management 3.3.5 |
18 | [ ] rabbitmq_stomp 3.3.5 |
19 | [ ] rabbitmq_test 3.3.5 |
20 | [ ] rabbitmq_tracing 3.3.5 |
21 | [e] rabbitmq_web_dispatch 3.3.5 |
22 | [ ] rabbitmq_web_stomp 3.3.5 |
23 | [ ] rabbitmq_web_stomp_examples 3.3.5 |
24 | [ ] sockjs 0.3.4-rmq3.3.5-git3132eb9 |
25 | [e] webmachine 1.10.3-rmq3.3.5-gite9359c7 |
E 为显式启动,e 为显式启动
重启rabbitmq-server,rabbitmq management插件生效,访问http://localhost:15672,rabbitmq web管理界面出现,使用默认的guest账号是访问不了的,在较老的版本中可以访问,但是处于安全考虑,需要一个非none的用户角色的账号来访问web管理界面。
应用与集群管理
应用管理
rabbitmqctl stop [pid_file]
用于停止运行RabbitMQ的Erlang虚拟机和RabbitMQ服务应用,其中pid_file默认情况下存放在Mnesia目录下,可以通过RABBIT_PID_FILE这个环境变量改变存放路径。注意,如果使用rabbitmq-server -detach这个带有-detach后缀的命令来启动RabbitMQ服务不会生成pid_file文件。rabbitmqctl shutdown
用于停止运行RabbitMQ的Erlang虚拟机和RabbitMQ服务应用,执行这个命令会阻塞直到Erlang虚拟机进程退出,这个命令与rabbitmqctl stop不同的是,它无需要指定pid_file就可以阻塞等待指定进程的关闭。rabbitmq stop_app
停止RabbitMQ服务应用,但是Erlang虚拟机还是处于运行状态。此命令的执行优先其他管理操作。rabbitmqctl start_app
启动RabbitMQ应用,此命令典型的用途是在执行了其他管理操作之后,重启之前停止的RabbitMQ应用。rabbitmqctl wait [pid_file]
等待RabbitMQ应用的启动,他会等待pid_file的创建,然后等待pid_file中所代表的进程启动。rabbitmqctl reset
将RabbitMQ节点重置还原到最初状态,包括从原来所在的集群中删除此节点,从管理数据库中删除所有的配置数据,如已配置的用户、vhost等,以及删除所以持久化的消息,执行rabbitmqctl reset命令前必须停止RabbitMQ应用。rabbitmqctl force_reset
强制将RabbitMQ节点重置还原到最初状态,不同于rabbitmqctl reset命令,rabbitmqctl force_reset命令不论当前管理数据库的状态和集群配置是什么,都无条件重置节点,它只在数据库或集群配置已损坏的情况下使用,执行rabbitmqctl force_reset命令前必须停止RabbitMQ应用。rabbitmqctl rotate_log {suffix}
指示RabbiMQ节点轮换日志文件,RabbitMQ节点会将原来的日志文件中的内容追加到“原始名称+后缀”的日志文件中,然后再将新的日志内容记录到新创建的日志中(与原日志文件同名)。
集群管理
rabbitmqctl join_cluster {cluster} [–ram]
将节点加入指定集群中,在这个命令执行前需要停止RabbitMQ应用并重置节点。rabbitmqctl cluster_status
显示集群的状态。rabbitmqctl change_cluster_node_type {disc|ram}
修改集群节点的类型,在这个命令执行前需要停止RabbitMQ应用。rabbitmqctl forget_cluster_node [–offline] {clusternode}
将节点从集群中删除,允许离线执行。rabbitmqctl update_cluster_nodes {clusternode}
在集群中的节点应用启动前咨询clusternode节点的最新消息,并更新相应的集群信息。这个和join_cluster不同,它不加入集群。
实例:
1 | #初始状态 |
2 | ~]# rabbitmqctl cluster_status |
3 | Cluster status of node rabbit@node1 ... |
4 | [{nodes,[{disc,[rabbit@INIT]},{ram,[rabbit@node1]}]}, |
5 | {running_nodes,[rabbit@INIT,rabbit@node1]}, |
6 | {cluster_name,<<"rabbit@INIT">>}, |
7 | {partitions,[]}] |
8 | ...done. |
9 | #关闭node1 |
10 | ~]# rabbitmqctl stop_app |
11 | Stopping node rabbit@node1 ... |
12 | ...done. |
13 | #之后将node2加入集群 |
14 | ~]# rabbitmqctl join_cluster rabbit@INIT |
15 | #再将INIT节点的应用关闭 |
16 | ~]# rabbitmqctl stop_app |
17 | #最后将node1节点的应用启动,会报错 |
18 | ~]# rabbitmqctl start_app |
19 | #如果在启动node1节点的应用之前咨询node2并更新相关信息则可以解决这个问题 |
20 | ~]# rabbitmqctl update_cluster_nodes rabbit@node2 |
21 | #启动node1节点 |
22 | ~]# rabbitmqctl start_app |
rabbitmqctl force_boot
确保节点可以启动,即使它不是最后一个关闭的节点,通常情况下,当关闭整个RabbitMQ集群时,重启的第一个节点应该是最后关闭的节点,因为它可以看到其他节点所看不到的事情。但是有时也可能出现异常情况,比如整个集群都掉电而所有节点都认为它不是最后一个关闭的,这种情况下,可以调用rabbitmqctl force_boot命令,这就告诉节点可以无条件地启动节点。在此节点关闭后,集群的任何变化,它都会丢失。如果最后一个关闭的节点永久丢失,那么需要优先使用rabbitmqctl forget_cluster_node –offline命令,确保镜像队列正常运转。rabbitmqctl sync_queue [-p vhost] {queue}
指示未同步队列queue的slave镜像可以同步master镜像的内容,同步期间此队列会被柱塞(所有的生产消费都会备柱塞),直到同步完成。rabbitmqctl cancel_sync_queue [-p vhost] {queue}
取消队列queue同步镜像的操作。rabbitmqctl set_cluster_name {name}
设置集群的名称,集群的名称默认是集群中的第一个节点名称。
服务端状态
- rabbitmqctl list_queues [-p vhost] [queueinfoitem…]
queueinfoitem:
- name: 队列名称
- durable: 队列是否持久化
- auto_delete: 队列是否自动删除
- arguments: 队列的参数
- policy: 应用到队列上的策略名称
- pid: 队列关联的Erlang进程的ID
- owner_pid: 处理排他队列连接的Erlang进程ID,如果此队列是排他性,此值将为空
- exclusive: 队列是否排他的
- exclusive_consumer_pid: 订阅到此排他队列的消费者相关的信道关联的Erlang进程ID,如果此队列是排他的,此值将为空
- exclusive_consumer_tag: 订阅到此排他队列的消费者的consumerTag,如果此队列是排他的,此值为空
- messages_ready: 准备发送给客户端的消息个数
- messages_unacknowledged: 发送给客户端但尚未应答的消息个数
- messages: 准备发送给客户端和未应答消息的总和
- messages_ready_ram: 驻留在内存中messages_ready的消息个数
- messages_unacknowledged_ram: 驻留在内存中messages_unacknowledged的消息个数
- messages_ram: 驻留在内存中的消息总数
- messages_persistent: 队列中的持久化消息的个数,对于非持久化的队列来说总是0
- messages_bytes: 队列中所有消息的大小总和,这里不包括消息属性或者任何其他开销
- messages_bytes_ready: 准备发送给客户端的消息的大小总和
- messages_bytes_unacknowledged: 发送给客户端但尚未应答的消息的大小总和
- messages_bytes_ram: 驻留在内存中的messages_bytes
- messages_bytes_persistent: 队列中持久化的messages_bytes
- disk_reads: 从队列启动开始,已从磁盘中读取该队列的消息总次数
- disk_write: 从队列启动开始,已向磁盘队列写消息的总次数
- consumer: 消费者数目
- consumer_utilisation: 队列中消息能够立刻投递给消费者的比率,介于0与1之间
- memory: 与队列相关的Erlang进程所消耗的内存
- slave_pids: 如果队列是镜像,列出所有slave尽享的pid
- synchronised_slave_pids: 如果队列是镜像的,列出所有已经同步的slave镜像的pid
- state: 队列状态,正常情况下running
- rabbitmqctl list_exchange [-p vhost] [exchangeinfoitem …]
exchangeinfoitem:
- name: 交换机的名称
- type: 交换机的类型
- durable: 设置是否持久化,持久化可以将交换机信息存盘,而在服务器重启的时候不会丢失相关信息
- auto_delete: 设置是否自动删除
- internal: 是否内置
- arguments: 其他一些结构化参数
- policy: 应用到交换机上的策略名称
- rabbitmqctl list_bindings [-p vhost] [bindinginfoitem…]
bindinginfoitem:
- source_name: 绑定中的消息来源的名称
- source_kind: 绑定中的消息来源的类型
- destination_name: 绑定中消息目的地的名称
- destination_kind: 绑定中消息目的地的种类
- routing_key: 绑定的路由键
- arguments: 绑定的参数
- rabbitmqctl list_connections [connectioninfoitem…]
connectioninfoitem:
- pid: 与连接相关的erlang进程的id
- name: 连接的名称
- port: 服务器端口
- host: 返回反向DNS获取的服务器主机名称或ip
- peer_port: 服务器对端端口,当一个客户端与服务器连接时,这个客户端的端口就是peer_port
- peer_host: 返回反向dns获取的对端主机名称或者ip
- ssl: 是否启用ssl
- ssl_protocol: ssl协议,如tlsv1
- ssl_key_exchange: ssl密钥交换算法,如rsa
- ssl_cipher: ssl加密算法,如aes_256_cbc
- ssl_hash: ssl哈希算法,如sha
- peer_cert_subject: 对端的ssl安全证书的主题
- peer_cert_issue: 对端ssl安全证书的发行者
- peer_cert_validity: 对端ssl安全证书的有效期
- state: 连接状态,包括starting,turing,opening,running,flow,blocking,blocked,closing和closed这几种
- channels: 该连接中的信道个数
- protocol: 使用的AMQP协议的版本
- auth_mechainism: 使用的sasl认证机制
- user: 与连接相关的用户名
- vhost: 与连接相关的vhost的名称
- timeout: 连接超时/协商的心跳间隔,单位为秒
- frame_max: 最大传输帧的大小
- channel_max: 此连接上的信道的最大数量,如果为0表示无上限
- client_properties: 在建立连接期间由客户端发送的信息属性
- recv_oct: 收到的字节数
- recv_cnt: 收到的数据包的个数
- send_oct: 发送的字节数
- send_cnt: 发送的数据包个数
- send_pend: 发送队列大小
- connected_at: 连接建立的事件戳
- rabbitctl list_channels [channelinfoitem…]
channelinfoitem:
- pid: 与连接相关的erlang进程id
- connection: 信道所属连接的erlang进程的id
- name: 信道的名称
- number: 信道的序号
- user: 与信道相关的用户名称
- vhost: 与信道相关的vhost
- transactional: 信道是否处于事物模式
- confirm: 信道是否处于publisher confirm模式
- consumer_count: 信道中的消费者的个数
- message_unacknowledged: 已投递但是还未被ack的消息个数
- message_uncommitted: 已接受但是还未提交事务的消息个数
- acks_uncommitted: 已ack收到但是还未提交事物的消息个数
- message_unconfirmed: 已发送但是还未确认的消息个数
- perfetch_count: 新消费者的Qos个数限制,0表示无上限
- global_prefetch_count: 整个信道Qos个数限制,0表示无上限
rabbitctl list_consumer [-p vhost]
列举消费者信息,以制表符分隔的已订阅的名称、相关信道的进程标识、consumerTag、是否需要消费端确认、perfetch_count及参数列表这些信息。rabbitctl status
Broker的状态rabbitctl node_health_check
对RabbitMQ节点进行健康检查,确认应用是否正常运行、list_queues和list_channels是否能够正常返回。rabbitmq environment
显示每个运行程序环境中每个变量的名称和值rabbitmqctl report
为所有服务状态生成一个服务器状态报告,并重定向输出到文件rabbitmqctl eval {expr}
执行任意erlang表达式
eval扩展
rabbitmqctl实现大多数MQ的操作,但是却无法对交换机、队列及绑定关系的创建(或删除)操作,rabbitmqctl eval {expr}的形式实现rabbitmqctl工具对交换机、队列及绑定关系。
- 创建一个交换机
declare(XName,Type,Durable,AutoDelete,Internal,Args)1
rabbitmqctl eval 'rabbit_exchange:declare({resource,<<"/">>,exchange,<<"exchange2">>},direct,true,false,false,[]).'
- XName: 交换机的命名细节,具体格式{resource,VHost,exchange,Name}
- Type: 交换机类型
- Durable: 是否需要持久化
- AutoDelete: 是否需要自动删除
- Internal: 是否是内置的交换机
- Args: 交换机的一些参数
删除交换机:1
rabbitmqctl eval 'rabbit_exchange:delete({resource,<<>"/">,exchange,<<"exchange2">>},false).'
- 创建一个队列
declare(QueueName,Durable,AutoDelete,Args,Owner)1
rabbitmqctl eval 'rabbit_amqqueue:declare({resource,<<"/">>,queue,<<"queue2">>},true,false,[],none).'
- QueueName: 队列的命名细节,具体格式为{resource,VHost,queue,Name}
- Durable: 是否持久化
- AutoDelete: 是否自动删除
- Args: 队列的其他选项参数
- Owner: 用于队列独占模式,一般为none
删除队列:1
rabbitmqctl eval 'rabbit_amqqueue:internal_delete({resource,<<"/">>,queue,<<"queue2>>}).'
- 绑定关系
add(Binding)1
rabbitmqctl eval 'rabbit_binding:add({binding,{resource,<<"/">>,exchange,<<"exchange2">>},<<"rk2">>,{resource,<<"/">>,queue,<<"queue2">>},[]}).'
- Binding: 绑定关系,可以是exchange到exchange,也可以是exchange到queue,具体格式{binding,Source,Key,Destination,Args},Source表示消息源,必须为交换机,Key为路由键,Destination为目的端
解除绑定关系:1
rabbitmqctl eval 'rabbitmq_binding:remove({binding,{resource,<<"/">>,exchange,<<"exchange2">>},<<"rk2>>,{resource,<<"/">>,queue,<<"queue2">>},[]}).'