玩转RabbitMQ之五(运行与管理MQ)

一、节点的概念 ??在玩转RabbitMQ之一:RabbitMQ的安装中,曾简单解释过Erlang跟RabbitMQ之间的关系,我们用JVM跟Java之间的关系做了类比。

??如果你对分布式集群的概念有点理解的话,你可能经常听到节点这个词,每台服务器都可以看成是一个节点,多个节点连接在一起组成了集群,对外提供服务时好像一台服务器一样。分布式的流行是因为可以根据应用程序请求压力和容量需求,动态地为集群增加和减少节点,这种弹性的集群节点管理为系统性能的扩容提供了极大的便利,同时也避免了机器资源的浪费,更重要的是增强了系统的健壮性和残存性,传统的BS模式靠的是单一的服务器节点,一旦这台机器挂掉,整个应用程序就全部挂掉了,分布式集群从理论上说就算100个节点组成的集群有99个挂掉了,只要有一个节点还是正常的它就能够对外提供服务。

??云计算也是在分布式的基础上发展起来的,之前看过一个视频,采访阿里云创始人王坚,他对云计算做了一个很形象的比喻:让计算资源像水龙头供水一样按需使用。这每一滴水,大概就像一个节点一样,一个个节点,组成了计算资源的“水流”。

??扯远了,回到Erlang节点,Erlang是RabbitMQ运行的环境或容器,RabbitMQ是节点上的应用程序,RabbitMQ数据库Mnesia也是运行在Erlang的应用程序,如果只是RabbitMQ应用程序崩溃了,并不会影响节点上的其他应用程序的运行,如果是Erlang节点崩溃了,容器都挂了上面的所有应用程序自然也会都挂掉,一般一个Erlang节点上只会运行一个RabbitMQ应用程序和配合使用的其他应用程序,你可以将一个RabbitMQ应用程序称为一个节点,但需要了解真正意义上的节点时什么含义。

玩转RabbitMQ之五(运行与管理MQ)
文章图片
Erlang节点和应用程序
二、节点管理

1、启动节点
??进入服务器上RabbitMQ可执行文件目录,执行下面命令启动节点:
[root@localhost huyihao]# cd /usr/sbin/ [root@localhost sbin]# rabbitmq rabbitmqadminrabbitmqctlrabbitmq-pluginsrabbitmq-server [root@localhost sbin]# rabbitmq-server RabbitMQ 3.6.6. Copyright (C) 2007-2016 Pivotal Software, Inc. ####Licensed under the MPL.See http://www.rabbitmq.com/ #### ##########Logs: /var/log/rabbitmq/rabbit@localhost.log ########/var/log/rabbitmq/rabbit@localhost-sasl.log ########## Starting broker... completed with 7 plugins.

??可以看到启动的RabbitMQ相关的信息,使用组合键ctrl+c就能关闭节点,这里可以看到默认的节点名为rabbit@localhost,组成规则是nodeName@domain/ip
[root@localhost sbin]# rabbitmq-server RabbitMQ 3.6.6. Copyright (C) 2007-2016 Pivotal Software, Inc. ####Licensed under the MPL.See http://www.rabbitmq.com/ #### ##########Logs: /var/log/rabbitmq/rabbit@localhost.log ########/var/log/rabbitmq/rabbit@localhost-sasl.log ########## Starting broker... completed with 7 plugins. ^C Session terminated, killing shell... ...已杀死。 [root@localhost sbin]# Stopping and halting node rabbit@localhost ... Gracefully halting Erlang VM

??有时你不想让一个终端窗口启动后就被占用了,那么可以选择后台启动节点:
[root@localhost sbin]# rabbitmq-server -detached Warning: PID file not written; -detached was passed.



2、停止节点
??如果是前台启动的节点,可以用组合键ctrl+c关闭节点,如果是后台呢?需要使用rabbitmqctl工具,对RabbitMQ进行管理时rabbitmqctl能满足大多数需求:
[root@localhost sbin]# rabbitmqctl stop Stopping and halting node rabbit@localhost ...



3、关闭应用程序而不停止节点
??你可能突发奇想,既然节点上运行了多个应用程序,那么是否能值关闭应用程序而不停止节点,rabbitmqctl可以做到,打印信息明显不同:
[root@localhost sbin]# rabbitmqctl stop_app Stopping node rabbit@localhost ...



4、日志
??很幸运,顺风顺水成功启动停止的节点,但有的时候节点可能发生故障,输入的命令可能有各种报错,这时候就需要查看日志了,从前台启动节点的打印输出信息可以知道,日志的位置位于/var/log/rabbitmq,我们进入看看:
[root@localhost sbin]# cd /var/log/rabbitmq/ [root@localhost rabbitmq]# ll 总用量 28416 drwxr-xr-x. 2 rootroot6 9月13 10:50 mnesia -rw-r--r--. 1 rabbitmq rabbitmq0 9月16 10:22 rabbit_1.log -rw-r--r--. 1 rabbitmq rabbitmq72099 9月15 23:40 rabbit_1.log-20180916 -rw-r--r--. 1 rabbitmq rabbitmq0 9月16 10:22 rabbit_1-sasl.log -rw-r--r--. 1 rabbitmq rabbitmq30953 9月13 22:11 rabbit_1-sasl.log-20180916 -rw-r--r--. 1 rabbitmq rabbitmq0 9月16 10:22 rabbit_2.log -rw-r--r--. 1 rabbitmq rabbitmq60117 9月15 23:38 rabbit_2.log-20180916 -rw-r--r--. 1 rabbitmq rabbitmq0 9月12 20:53 rabbit_2-sasl.log -rw-r--r--. 1 rabbitmq rabbitmq0 9月16 10:22 rabbit_3.log -rw-r--r--. 1 rabbitmq rabbitmq10545 9月13 22:11 rabbit_3.log-20180916 -rw-r--r--. 1 rabbitmq rabbitmq0 9月12 21:08 rabbit_3-sasl.log -rw-r--r--. 1 rabbitmq rabbitmq0 9月26 20:28 rabbit_a.log -rw-r--r--. 1 rabbitmq rabbitmq 3413413 9月16 22:47 rabbit_a.log-20180926 -rw-r--r--. 1 rabbitmq rabbitmq0 9月26 20:28 rabbit_a-sasl.log -rw-r--r--. 1 rabbitmq rabbitmq 5226269 9月16 19:31 rabbit_a-sasl.log-20180926 -rw-r--r--. 1 rabbitmq rabbitmq0 9月26 20:28 rabbit_b.log -rw-r--r--. 1 rabbitmq rabbitmq 1789380 9月16 22:48 rabbit_b.log-20180926 -rw-r--r--. 1 rabbitmq rabbitmq0 9月26 20:28 rabbit_b-sasl.log -rw-r--r--. 1 rabbitmq rabbitmq 5022542 9月16 22:48 rabbit_b-sasl.log-20180926 -rw-r--r--. 1 rabbitmq rabbitmq585944 9月28 21:16 rabbit@localhost.log -rw-r--r--. 1 rabbitmq rabbitmq910 8月15 08:02 rabbit@localhost.log-20180819.gz -rw-r--r--. 1 rabbitmq rabbitmq2278 8月26 19:31 rabbit@localhost.log-20180826.gz -rw-r--r--. 1 rabbitmq rabbitmq656 9月1 15:09 rabbit@localhost.log-20180902.gz -rw-r--r--. 1 rabbitmq rabbitmq1316 9月2 23:36 rabbit@localhost.log-20180909.gz -rw-r--r--. 1 rabbitmq rabbitmq2729 9月13 21:32 rabbit@localhost.log-20180916.gz -rw-r--r--. 1 rabbitmq rabbitmq 7209837 9月17 21:13 rabbit@localhost.log-20180926 -rw-r--r--. 1 rabbitmq rabbitmq 1594920 9月28 21:16 rabbit@localhost-sasl.log -rw-r--r--. 1 rabbitmq rabbitmq289934 9月17 19:59 rabbit@localhost-sasl.log-20180917.gz -rw-r--r--. 1 rabbitmq rabbitmq 3699981 9月17 21:13 rabbit@localhost-sasl.log-20180926 -rw-r--r--. 1 rabbitmq rabbitmq0 9月16 10:22 rabbit.log -rw-r--r--. 1 rabbitmq rabbitmq38817 9月15 23:41 rabbit.log-20180916 -rw-r--r--. 1 rabbitmq rabbitmq0 9月16 10:22 rabbit-sasl.log -rw-r--r--. 1 rabbitmq rabbitmq802 9月13 11:11 rabbit-sasl.log-20180916

??可以看到目录下有很多文件,还有一个mnesia的目录,这是RabbitMQ的数据库数据存储的目录,除了rabbit@localhost.log,还看到很多前缀一样的文件,后面带了日期,很明显这是对每日日志的备份,打印最近的20行rabbit@localhost.log看看:
[root@localhost rabbitmq]# tail -n 20 rabbit@localhost.log {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,247}]}]}=INFO REPORT==== 28-Sep-2018::21:16:22 === Server startup complete; 7 plugins started. * rabbitmq_management * rabbitmq_shovel * amqp_client * rabbitmq_web_dispatch * webmachine * mochiweb * rabbitmq_management_agent=INFO REPORT==== 28-Sep-2018::21:16:25 === Stopping RabbitMQ=INFO REPORT==== 28-Sep-2018::21:16:25 === stopped TCP Listener on [::]:5672=INFO REPORT==== 28-Sep-2018::21:16:26 === Stopped RabbitMQ application

??可以看到RabbitMQ的命令日志,上面那一块是启动了一些插件,下面关闭了RabbitMQ,断开与5672端口的链接,最后停止RabbitMQ应用程序,从这里可以知道RabbitMQ默认的端口是5672,如果执行命令时发生报错,那么也可以在RabbitMQ日志里找到相应的日志。


三、RabbitMQ配置 ??RabbitMQ默认配置文件的目录位于/etc/rabbitmq,在该目录下可以看到两个配置文件:
[root@localhost rabbitmq]# ll 总用量 8 -rw-r--r--. 1 root root51 9月16 22:58 enabled_plugins -rw-r--r--. 1 root root 1752 9月16 19:30 rabbitmq.config

??enabled_plugins看名字就知道是配置要启用哪些RabbitMQ插件,有许多常用的插件跟RabbitMQ一起打包安装比如管理控制台rabbitmq_management,每个插件都有一个对应ez文件,默认位于/usr/lib/rabbitmq/lib/rabbitmq_server-3.6.6/plugins,从配置的内容看启用了三个插件。
[root@localhost rabbitmq]# cat enabled_plugins [amqp_client,rabbitmq_management,rabbitmq_shovel].

??rabbitmq.config是RabbitMQ的系统配置文件,如果没有这个文件,则可自行创建,打印文件内容,看看配置了些什么东西。
[root@localhost rabbitmq]# cat rabbitmq.config [ {mnesia, [{dump_log_write_threshold, 1000}]}, {rabbit, [{vm_memory_high_watermark, 0.4}]}, ]

??配置文件的格式最外层是中括号(数组),每个配置元素都以花括号表示,每个元素的值又可能是一个数组,实际上数组允许多重嵌套,可以看到第一个配置mnesia数据库的配置,配置了一个dump_log_write_threshold的配置项,值为1000,这个参数表示将仅限追加的日志内容刷出/转储到真是数据库文件的频度,为什么不产生一条数据就马上存储到数据库文件呢?而是每满1000条就存一次,这样做的目的是为了降低I/O(读写)的次数,避免对系统性能造成影响,当然只有持久化消息才需要将数据持久化(存储到数据库文件中)。

??vm_memory_high_watermark为控制RabbitMQ允许消耗的内存最大比例,这里设为0.4即最多允许MQ消耗服务器40%的内存。

??Mnesia和Rabbit配置项罗列如下:
(1)Mnesia配置选项
配置项 默认值 描述
dump_log_write_threshold(整型) 100 将仅限追加的日志内容刷出/转储至真实数据库文件的频度。它明确制定了在转储操作发生前,必须有多少个条目存储在日志中。设置更高的数值将减少I/O负载并增加持久化消息的性能
(2)Rabbit配置选项
配置项 默认值 描述
tcp_listeners({"ip地址":端口号} 数组) [{"0.0.0.0", 5672},] 定义了RabbitMQ应该监听的非SSL加密通信的IP地址和端口
ssl_listeners({"ip地址":端口号} 数组) 定义了RabbitMQ应该监听的SSL加密通信的IP地址和端口
ssl_options({"键":值} 数组) 指定SSL相关的选项。有效的选项有cacertfile(CA证书文件)、certfile(服务器证书文件)、keyfile(服务器密钥文件)和fail_if_no_peer_cert(需要客户端安装有效证书:True/False)
vm_memory_high_watermark(十进制百分数) 0.4 控制RabbitMQ允许消耗的内存。它以十进制数值的形式明确了Rabbit允许使用的安装内存百分比(0.4=40%)
msg_store_file_size_limit(整型:字节) 16777216 RabbitMQ垃圾收集存储内容之前,消息存储数据库的最大大小
queue_index_max_journal_entries 262144 在转储到消息存储数据库并提交之前,消息存储日志里的最大条目数
??除了这些配置,RabbitMQ的很多插件也是允许在配置文件中做配置并随启动生效的,具体的配置项要看使用的插件。


四、权限管理 ??RabbitMQ的权限主要针对用户而言,有点类似Linux的文件访问权限,RabbitMQ的用户权限由三部分组成:读、写、配置,如下表所示:
AMQP命令 配置
exchange.declare exchange
exchange.delete exchange
queue.declare queue
queue.delete queue
queue.bind queue exchange
basic.publish exchange
basic.get queue
basic.consume queue
queue.purge queue
??交换器、队列的声明和删除属于配置权限;队列的绑定需要有对队列的写权限和对交换器的读权限;消息发布到交换器上需要对交换器的写权限;消息的获取和消费需要队列的读权限;队列的清空也属于读权限。

??权限管理可以对单个用户在不同的vhost上设置不同的权限,不同的vhost上运行着不同的应用程序,达到对用户为不同的应用程序设置不同级别的权限的目的,如下图所示:

玩转RabbitMQ之五(运行与管理MQ)
文章图片
RabbitMQ权限工作原理:用户可以为连接到RabbitMQ主机的应用程序设置不同级别的权限(读、写、配置)
1、用户管理
??要管理用户权限先得有用户,RabbitMQ默认的用户是guest,密码guest,我们使用rabbitmqctl来操作管理RabbitMQ。

??查看MQ中的用户列表:
[root@localhost huyihao]# rabbitmqctl list_users Listing users ... monitor [administrator] guest[administrator]

??添加用户(用户名:huyihao,密码:666):
[root@localhost huyihao]# rabbitmqctl add_user huyihao 666 Creating user "huyihao" ...

??重新看一下用户列表:
[root@localhost huyihao]# rabbitmqctl list_users Listing users ... monitor [administrator] huyihao [] guest[administrator]

??删除用户:
[root@localhost huyihao]# rabbitmqctl delete_user huyihao Deleting user "huyihao" ...

??哪一天你把用户密码忘了,需要重置:
[root@localhost huyihao]# rabbitmqctl add_user huyihao 666 Creating user "huyihao" ... [root@localhost huyihao]# rabbitmqctl change_password huyihao 777 Changing password for user "huyihao" ...



2、虚拟主机管理与用户授权
??RabbitMQ默认的虚拟主机是"/",查看系统中所有的vhost:
[root@localhost huyihao]# rabbitmqctl list_vhosts Listing vhosts ... /

??假设现在你有一个应用要使用mq,为了跟其他原有的应用区分开互相隔离,需要创建一个新的vhost:
[root@localhost huyihao]# rabbitmqctl add_vhost newapp Creating vhost "newapp" ...

??既然每个用户对每个vhost的权限都是独立的,你可能好奇有没有默认的权限之类的东西,使用下面的命令来查看用户对每个vhosts的权限列表:
[root@localhost huyihao]# rabbitmqctl list_user_permissions huyihao Listing permissions for user "huyihao" ... # 默认是空的,说明新建的用户不会对任何一个vhost(包括默认vhost)有任何操作权限!

??当MQ管理员定期想检查某个应用对应的vhosts对不同用户的授权情况如何时,可使用以下命令:
[root@localhost huyihao]# rabbitmqctl list_permissions -p newapp Listing permissions in vhost "newapp" ... # 默认是空的,说明新建的用户不会对任何一个用户(包括guest)授予任何权限!

【玩转RabbitMQ之五(运行与管理MQ)】??现在我们想让新建的用户huyihao对虚拟主机newapp授予读写配置的权限,可使用如下命令:
[root@localhost huyihao]# rabbitmqctl set_permissions -p newapp huyihao ".*" ".*" ".*" Setting permissions for user "huyihao" in vhost "newapp" ... [root@localhost huyihao]# rabbitmqctl list_permissions -p newapp Listing permissions in vhost "newapp" ... huyihao .*.*.* [root@localhost huyihao]# rabbitmqctl list_user_permissions huyihao Listing permissions for user "huyihao" ... newapp.*.*.* # 授权命令的格式:rabbitmqctl set_permissions -p [vhost] [user] [配置权限] [读权限] [写权限] # 授权正则表达式: # (1)".*": 匹配任何队列和交换器 # (2)"xx.*": 只匹配名字以xx开头的交换器和队列 # (3)"": 不匹配任何队列和交换器(就是没有权限)

    推荐阅读