管理RabbitMQ
RabbitMQ 默认有一个根VHOST 当然一般情况下我们都会创建属于某个应用程序的vhost 去方便管理。在个节点当中vhost 与 vhost 之间是互相隔离的,所以在多个不同的vhost当中可以创建相同名称的 交换器(exchange) 队列(queue)。这个概念就像是数据库一样,mysql当中有个多个不同的数据库,多个数据库当中可以使用相同的表名的概念一样。
接下来我们就来开始写一下如何创建vhost~
MacBook-Pro:rabbitmq Tony$ /usr/local/sbin/rabbitmqctl add_vhost APP_A
Creating vhost "APP_A" ...
MacBook-Pro:rabbitmq Tony$ /usr/local/sbin/rabbitmqctl delete_vhost APP_A
Deleting vhost "APP_A" ...
MacBook-Pro:rabbitmq Tony$ /usr/local/sbin/rabbitmqctl list_vhosts
Listing vhosts ...
/
APP_A
APP_B
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1"); //服务器地址
factory.setUsername("guest"); //默认用户名
factory.setPassword("guest"); //默认密码
factory.setVirtualHost("APP_A"); //vhost名称
factory.setPort(5672); //默认端口
启动和停止RabbitMQ RabbitMQ启动的方式比较简单,但是关闭会有几种方式去个关闭,而且关闭的情况各有不同。
MacBook-Pro:~ Tony$ /usr/local/sbin/rabbitmq-server
RabbitMQ 3.5.6. Copyright (C) 2007-2015 Pivotal Software, Inc.
## ## Licensed under the MPL. See http://www.rabbitmq.com/
## ##
########## Logs: /usr/local/var/log/rabbitmq/rabbit@localhost.log
###### ## /usr/local/var/log/rabbitmq/rabbit@localhost-sasl.log
##########
Starting broker... completed with 10 plugins.
我不建议,直接在这里使用ctrl+C的方法直接结束应用程序,我这里推荐以下方式去关闭RabbitMQ。使用这种方式有效干净关闭,并且保护好持久化的队列。
MacBook-Pro:rabbitmq Tony$ /usr/local/sbin/rabbitmqctl stop
Stopping and halting node rabbit@localhost ...
当然也可以使用 -n rabbit@[hostname]来关闭其他远程节点。这个会在介绍群集的时候在贴出代码
MacBook-Pro:lib Tony$ /usr/local/sbin/rabbitmqctl status
Status of node rabbit@localhost ...
[{pid,10780},
{running_applications,
[{rabbitmq_management_visualiser,"RabbitMQ Visualiser","3.5.6"},
{rabbitmq_management,"RabbitMQ Management Console","3.5.6"},
{rabbitmq_web_dispatch,"RabbitMQ Web Dispatcher","3.5.6"},
{webmachine,"webmachine","1.10.3-rmq3.5.6-gite9359c7"},
{mochiweb,"MochiMedia Web Server","2.7.0-rmq3.5.6-git680dba8"},
{rabbitmq_mqtt,"RabbitMQ MQTT Adapter","3.5.6"},
{rabbitmq_stomp,"Embedded Rabbit Stomp Adapter","3.5.6"},
{rabbitmq_management_agent,"RabbitMQ Management Agent","3.5.6"},
{rabbitmq_amqp1_0,"AMQP 1.0 support for RabbitMQ","3.5.6"},
{rabbit,"RabbitMQ","3.5.6"},
{os_mon,"CPO CXC 138 46","2.3.1"},
{inets,"INETS CXC 138 49","5.10.6"},
{mnesia,"MNESIA CXC 138 12","4.12.5"},
{amqp_client,"RabbitMQ AMQP Client","3.5.6"},
{xmerl,"XML parser","1.3.7"},
{sasl,"SASL CXC 138 11","2.4.1"},
{stdlib,"ERTS CXC 138 10","2.4"},
{kernel,"ERTS CXC 138 10","3.2"}]},
{os,{unix,darwin}},
{erlang_version,
"Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [async-threads:64] [hipe] [kernel-poll:true]\n"},
{memory,
[{total,43180016},
{connection_readers,0},
{connection_writers,0},
{connection_channels,0},
{connection_other,5616},
{queue_procs,19712},
{queue_slave_procs,0},
{plugins,868704},
{other_proc,13887864},
{mnesia,72792},
{mgmt_db,234672},
{msg_index,47824},
{other_ets,1275216},
{binary,19872},
{code,20760734},
{atom,711569},
{other_system,5275441}]},
{alarms,[]},
{listeners,
[{clustering,25672,"::"},
{amqp,5672,"127.0.0.1"},
{stomp,61613,"::"},
{mqtt,1883,"::"}]},
{vm_memory_high_watermark,0.4},
{vm_memory_limit,1401384140},
{disk_free_limit,50000000},
{disk_free,8082620416},
{file_descriptors,
[{total_limit,156},{total_used,5},{sockets_limit,138},{sockets_used,3}]},
{processes,[{limit,1048576},{used,198}]},
{run_queue,0},
{uptime,8267}]
首先 看看 rabbitmq-env.conf 由于本人也没有碰过 rabbitmq-env.conf 这个文件所以我也 翻了一下官网,看看这个文件是怎么一回事,因为在参考的学习的书本 rabbitmq in action 中的管理rabbit 的章节当中,并没有提及到 rabbitmq-env.conf 文件 只有提及 rabbitma.config 。以下是官网对 rabbitmq-env.conf 文件的介绍 我这里就引用一下。
rabbitmq-env.conf — default settings for RabbitMQ AMQP server
/etc/rabbitmq/rabbitmq-env.conf contains variable settings that override the defaults built in to the RabbitMQ startup scripts.
The file is interpreted【解析】 by the system shell, and so should consist of a sequence【线性】 of shell environment【环境】 variable【变量】 definitions【定义】. Normal shell syntax【语法】 is permitted (since the file is sourced using the shell “.” operator), including line comments starting with “#”.
In order of preference【偏好】, the startup scripts get their values from the environment, from /etc/rabbitmq/rabbitmq-env.conf and finally from the built-in default values. For example, for the RABBITMQ_NODENAME setting,
RABBITMQ_NODENAME
from the environment is checked first. If it is absent【缺失】 or equal to the empty string, then
NODENAME
from /etc/rabbitmq/rabbitmq-env.conf is checked. If it is also absent or set equal to the empty string then the default value from the startup script is used.
The variable names in /etc/rabbitmq/rabbitmq-env.conf are always equal to the environment variable names, with the RABBITMQ_ prefix removed: RABBITMQ_NODE_PORT from the environment becomes NODE_PORT in the /etc/rabbitmq/rabbitmq-env.conf file, etc.
英文跟我一样一般般的看这里,我解释一下:
其实就是说 一般情况下RabbitMQ会有所有环境变量的默认值,他会检查rabbitmq-env.conf这个文件并且如果缺失的参数或者参数为空字符串都会以默认的参数值为准。其实看看官方的英文解析对以后学习很大帮助 我也是努力地去看。
这是官方给出来的example
# I am a complete /etc/rabbitmq/rabbitmq-env.conf file.
# Comment lines start with a hash character.
# This is a /bin/sh script file - use ordinary envt var syntax
NODENAME=hare
但是我在我的MacBook 上寻找了非常多的方法,也无法让配置生效,由于我是用brew命令进行安装的rabbitmq 固然我看了一下文档 不应该在 /etc/rabbitmq/这个目录下去建立这个变量文件,所有我就开始郁闷了。我看了一下文档是这样去写那个位置的:
Generic UNIX - $RABBITMQ_HOME/etc/rabbitmq/rabbitmq-env.conf
Debian - /etc/rabbitmq/rabbitmq-env.conf
RPM - /etc/rabbitmq/rabbitmq-env.conf
Mac OS X (Homebrew) - ${install_prefix}/etc/rabbitmq/rabbitmq-env.conf, the Homebrew prefix is usually /usr/local
Windows - %APPDATA%\RabbitMQ\rabbitmq-env-conf.bat
说明配置文件应该在那个目前当中去建立,最终我找到安装的目录:
MacBook-Pro:rabbitmq Tony$ ls -al /usr/local/sbin/
total 48
drwxrwxrwx 8 root wheel 272 10 27 11:16 .
drwxr-xr-x 25 root wheel 850 10 27 11:13 ..
lrwxr-xr-x 1 Tony wheel 47 10 27 11:16 rabbitmq-defaults -> ../Cellar/rabbitmq/3.5.6/sbin/rabbitmq-defaults
lrwxr-xr-x 1 Tony wheel 42 10 27 11:16 rabbitmq-env -> ../Cellar/rabbitmq/3.5.6/sbin/rabbitmq-env
lrwxr-xr-x 1 Tony wheel 46 10 27 11:16 rabbitmq-plugins -> ../Cellar/rabbitmq/3.5.6/sbin/rabbitmq-plugins
lrwxr-xr-x 1 Tony wheel 45 10 27 11:16 rabbitmq-server -> ../Cellar/rabbitmq/3.5.6/sbin/rabbitmq-server
lrwxr-xr-x 1 Tony wheel 43 10 27 11:16 rabbitmqadmin -> ../Cellar/rabbitmq/3.5.6/sbin/rabbitmqadmin
lrwxr-xr-x 1 Tony wheel 41 10 27 11:16 rabbitmqctl -> ../Cellar/rabbitmq/3.5.6/sbin/rabbitmqctl
看到这里应该知道他的具体位置了吧~
MacBook-Pro:rabbitmq Tony$ pwd
/usr/local/Cellar/rabbitmq/3.5.6/etc/rabbitmq
MacBook-Pro:rabbitmq Tony$ ls
rabbitmq-env.conf rabbitmq.config.example
然后我建立 rabbitmq-env.conf 之后 是然并卵的~ 我修改了一下端口号,结果还是没有生效。我就差重启电脑了。我目前在按照一台linux的rabbitmq 一会在 LINUX下测试一下。 后面补充一下:在LINUX环境当中测试的确没有任何问题,WHAT THE FUCK 为什么mac os上没有生效~? LINUX的配置文件位置 /etc/rabbitmq/rabbitmq-env.conf
关于环境配置 引用一下 官网:
关于配置的官方文档,你不点击一下看看吗?
好再说说rabbitmq.config 哎哟,好没有底气啊。测试不出来,算了吧··· 一会再尝试一下 linux 看看可不可以。
官方提出的最小配置如下:
[
{rabbit, [{tcp_listeners, [5673]}]}
].
其实配置上非常像 JSON 只要仔细观察就能分析出它的编写格式~ 遗憾的是经过测试也是没有生效。之后后面慢慢查看原因了。
后面补充在LINUX 上同样生效,就是不知道为什么mac上不生效。
以下就是官方提供的配置文件位置:
由于目前我已经在linux之中安装好rabbitMQ,我要抛弃mac 的rabbitMQ了。但是在远程访问rabbitMQ会出错,因为guest用户只能在回环地址中使用,也就是说你只能在本地使用。 然后我给出一下JAVA 远程连接时的错误log
Exception in thread "main" com.rabbitmq.client.PossibleAuthenticationFailureException: Possibly caused by authentication failure
at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:355)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:516)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:533)
at com.maxfunner.Consumer.createConnectionAndChannel(Consumer.java:35)
at com.maxfunner.Consumer.main(Consumer.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: com.rabbitmq.client.ShutdownSignalException: connection error; reason: java.net.SocketException: Connection reset
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:67)
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:33)
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:343)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:216)
at com.rabbitmq.client.impl.AMQChannel.rpc(AMQChannel.java:202)
at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:347)
... 9 more
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:209)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readUnsignedByte(DataInputStream.java:288)
at com.rabbitmq.client.impl.Frame.readFrom(Frame.java:95)
at com.rabbitmq.client.impl.SocketFrameHandler.readFrame(SocketFrameHandler.java:131)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:515)
By default, the guest user is prohibited from connecting to the broker remotely; it can only connect over a > loopback interface (i.e. localhost). This applies both to AMQP and to any other protocols enabled via plugins. Any > other users you create will not (by default) be restricted in this way.
如果我们希望在远程的地方使用到guest用户我们可以修改配置
[root@centOSFrist ~]# vim /etc/rabbitmq/rabbitmq.config
[
{rabbit, [ {tcp_listeners, [5673]},
{loopback_users,[]}
]}
].
重启一下服务就生效了,目前的配置是 rabbit节点上 端口号为5673 loopback用户为空。
[root@centOSFrist ~]# systemctl restart rabbitmq-server.service
启动之后便能够连接到远程的rabbitmq当中 。
先看看如何去创建用户:
MacBook-Pro:sbin Tony$ ./rabbitmqctl add_user tony tonypwd
Creating user "tony" ...
成功创建了一个用户名为tony 密码为tonypwd 的用户。
删除用户:
MacBook-Pro:sbin Tony$ ./rabbitmqctl delete_user tony
Deleting user "tony" ...
删除一个用户名为tony 的用户
我们可以使用命令去查看用户信息
MacBook-Pro:sbin Tony$ ./rabbitmqctl list_users
Listing users ...
guest [administrator]
tony []
目前有两个用户 一个是 guest 还有就是 tony 然而guest 是 administrator
接下来我们来修改一下密码,注意如果删除了用户连同用户的权限也会同样删除。
MacBook-Pro:sbin Tony$ ./rabbitmqctl change_password tony 123456
Changing password for user "tony" ...
修改了用户名为tony的密码,现在的密码被修改为123456
然后说重点,权限。这个是开发的过程之中用的应该最为常见。
RabbitMQ的权限也是非常容易让人理解的,传统的ACL风格。
读权限:有关消费消息的任何操作,包括 清除 整个队列。
写权限:发布消息
配置权限:队列和交换器的创建和删除。
注意:权限是没有办法跨越vhost的,如果你想某个用户拥有两个vhost的权限,你必须指定两条ACL。
先赋予tony用户对vhost 名称为 APP_A 的全部权限。
[root@centOSFrist ~]# rabbitmqctl set_permissions -p APP_A tony ".*" ".*" ".*"
Setting permissions for user "tony" in vhost "APP_A" ...
然后我们可以尝试修改一下tony这个用户的权限
[root@centOSFrist ~]# rabbitmqctl set_permissions -p APP_A tony \
> "tony-.*" "tony-.*" ".*"
Setting permissions for user "tony" in vhost "APP_A" ...
tony 用户目前可以对APP_A 这个vhost 配置tony-开头的交换器/队列 同时可以在tony-开头的交换器或者队列发布消息 可以订阅所有消息。
在JAVA 应用程序中测试一下(截取重点代码,以及错误LOG)
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.0.21");
factory.setUsername("tony");
factory.setPassword("tonypwd");
factory.setVirtualHost("APP_A");
factory.setPort(5673);
创建交换器和队列:
private static final String EXCHANGE_NAME = "MY_EXCHANGE";
this.channel.exchangeDeclare(EXCHANGE_NAME,"direct",false,true,null); //最好也创建一下交换器,反正已经创建也没有关系
this.channel.queueDeclare("QUEUE_A",false,false,true,null);
this.channel.queueBind("QUEUE_A",EXCHANGE_NAME,"KEY_A");
由于我目前创建的交换器名称为 MY_EXCHANGE 所以就出现了错误的LOG:
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; reason:
{#method<channel.close>(reply-code=403, reply-text=ACCESS_REFUSED -
access to exchange 'MY_EXCHANGE' in vhost 'APP_A' refused for user 'tony',
class-id=40, method-id=10), null, ""}
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:67)
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:33)
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:343)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:216)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:118)
... 10 more
当我修改了所有的交换器和队列的名称为tony-EXCHANGE tony-QUEUE 之后就一切就正常了,我们可以使用命令查看目前某个vhost中的配置:
[root@centOSFrist ~]# rabbitmqctl list_permissions
Listing permissions in vhost "/" ...
guest .* .* .*
[root@centOSFrist ~]# rabbitmqctl list_permissions -p APP_A
Listing permissions in vhost "APP_A" ...
tony tony-.* tony-.* .*
还可以使用命令查看某个用户的权限:
[root@centOSFrist ~]# rabbitmqctl list_user_permissions tony
Listing permissions for user "tony" ...
APP_A tony-.* tony-.* .*
删除某一个用户权限如下:
[root@centOSFrist ~]# rabbitmqctl clear_permissions -p APP_A tony
Clearing permissions for user "tony" in vhost "APP_A" ...
[root@centOSFrist ~]# rabbitmqctl list_user_permissions tony
Listing permissions for user "tony" ...
none、management、policymaker、monitoring、administrator
none :
不能访问 management plugin
management :
可以使用AMQP所有功能
列出自己可以通过AMQP登入VHOST
查看自己的vhost中的队列、交换器、绑定
查看和关闭自己的信道(channel) 和 connection
查看自己有关的vhost的“全局”的统计信息和其他用户在这些vhost中的活动。
policymaker :
management的所有权限
对自己的vhost所属的policies和parameters 进行增删改查
monitoring :
management的所有权限
查看所有vhost
查看节点的数据使用情况
所有vhost的全局的统计信息
administrator :
什么都可以干~
设置用户角色权限:
[root@centOSFrist ~]# rabbitmqctl set_user_tags tony policymaker
Setting tags for user "tony" to [policymaker] ...
[root@centOSFrist ~]# rabbitmqctl list_users
Listing users ...
guest [administrator]
tony [policymaker]
这个的权限的体现具体会在RabbitMQ的web控制台上面介绍。
[root@centOSFrist ~]# rabbitmqctl list_queues -p APP_A
Listing queues ...
tony-QUEUE 0
QUEUE_A 6
------------
目前只显示了 队列名称 和对应的 消息总数,除此之外提供一下参数:
<queueinfoitem> must be a member of the list [name, durable, auto_delete,
arguments, policy, pid, owner_pid, exclusive, exclusive_consumer_pid,
exclusive_consumer_tag, messages_ready, messages_unacknowledged, messages,
messages_ready_ram, messages_unacknowledged_ram, messages_ram,
messages_persistent, message_bytes, message_bytes_ready,
message_bytes_unacknowledged, message_bytes_ram, message_bytes_persistent,
head_message_timestamp, disk_reads, disk_writes, consumers,
consumer_utilisation, memory, slave_pids, synchronised_slave_pids, state].
[root@centOSFrist ~]# rabbitmqctl list_queues -p APP_A name durable pid memory
Listing queues ...
tony-QUEUE false <[email protected]> 14040
QUEUE_A false <[email protected]> 21816
[root@centOSFrist ~]# rabbitmqctl list_exchanges -p APP_A
Listing exchanges ...
amq.headers headers
amq.fanout fanout
amq.direct direct
amq.match headers
direct
amq.topic topic
amq.rabbitmq.trace topic
MY_EXCHANGE direct
tony-EXCHANGE direct
其他参数如下:
<exchangeinfoitem> must be a member of the list [name, type, durable,
auto_delete, internal, arguments, policy].
RabbitMQ的日志默认位置在:
[root@centOSFrist ~]# ls -ll /var/log/rabbitmq/
总用量 32
-rw-r--r--. 1 rabbitmq rabbitmq 13247 11月 2 11:37 rabbit@centOSFrist.log -rw-r--r--. 1 rabbitmq rabbitmq 0 11月 1 17:04 rabbit@centOSFrist-sasl.log -rw-r--r--. 1 root root 60 11月 1 17:58 shutdown_err -rw-r--r--. 1 root root 49 11月 1 17:58 shutdown_log -rw-r--r--. 1 root root 60 11月 1 17:58 startup_err -rw-r--r--. 1 root root 355 11月 1 17:58 startup_log
[email protected] -> 节点名称为rabbit 主机为 centOSFrist 的日志 主要看这个日志
[email protected] -> 节点名称为rabbit 主机为 centOSFrist 的系统应用程序支持库日志 大部分是关于 Erlang的日志
可以使用tail 命令查看实时日志情况:
[root@centOSFrist ~]# tail -f /var/log/rabbitmq/[email protected]
=ERROR REPORT==== 2-Nov-2016::11:36:57 ===
Error on AMQP connection <0.626.0> (192.168.0.2:59664 -> 192.168.0.21:5673, user: 'guest', state: opening):
access to vhost 'APP_A' refused for user 'guest'
=INFO REPORT==== 2-Nov-2016::11:36:57 ===
closing AMQP connection <0.626.0> (192.168.0.2:59664 -> 192.168.0.21:5673)
=INFO REPORT==== 2-Nov-2016::11:37:32 ===
accepting AMQP connection <0.632.0> (192.168.0.2:59680 -> 192.168.0.21:5673)
如果日志需要轮换 可以使用命令进行轮换日志
[root@centOSFrist ~]# rabbitmqctl rotate_logs 1
Rotating logs to files with suffix "1" ...
[root@centOSFrist ~]# ls -ll /var/log/rabbitmq/
总用量 32
-rw-r--r--. 1 rabbitmq rabbitmq 0 11月 2 11:58 rabbit@centOSFrist.log -rw-r--r--. 1 rabbitmq rabbitmq 13320 11月 2 11:58 rabbit@centOSFrist.log1 -rw-r--r--. 1 rabbitmq rabbitmq 0 11月 2 11:58 rabbit@centOSFrist-sasl.log -rw-r--r--. 1 rabbitmq rabbitmq 0 11月 2 11:58 rabbit@centOSFrist-sasl.log1 -rw-r--r--. 1 root root 60 11月 1 17:58 shutdown_err -rw-r--r--. 1 root root 49 11月 1 17:58 shutdown_log -rw-r--r--. 1 root root 60 11月 1 17:58 startup_err -rw-r--r--. 1 root root 355 11月 1 17:58 startup_log
最后贴下我参考的官网链接:
权限 : http://www.rabbitmq.com/access-control.html
配置 : http://www.rabbitmq.com/configure.html
rabbitmqctrl : http://www.rabbitmq.com/man/rabbitmqctl.1.man.html