3.运行和管理Rabbit
3.1启动节点
节点描述的是一个Erlang节点运行着一个Erlang应用程序。
当你运行一个java的时候,jvm的一个实例就启动了,并且开始执行指定的java程序。与之相似,erlang也有虚拟机,而虚拟机的每个实例我们称之为
节点。不同于jvm,多个erlang应用程序可以运行在同一个节点之上。更重要的是,节点之间可以进行本地通信(不管它们是否真的在同一台服务器上)。举例
来说,由于erlang的魔力,一个运行在A节点的应用程序可以调用B节点上的应用程序的方法,就好像这些函数是本地方法一样。同时,由于某些原因,如果
应用程序(如rabbitMQ)由于某些原因崩溃了,erlang节点会自动尝试重启应用程序。
一个erlang节点,上面可以跑多个应用程序(如RabbitMQ)。
//启动
/usr/lib/rabbitmq/bin/rabbitmq-server
//关闭节点
选 abort
//优雅的关闭节点,退出
rabbitmqctl stop
3.1.3 关闭和重启应用程序的区别
我们讨论了如何停止整个RabbitMQ节点(应用程序和Erlang节点)。有时候你只想重启rabbit应用程序,而同时保持erlang节点运行。对集群来说,这种做法是必须的。
rabbitmq-server 同时启动了节点和应用程序,因为它把rabbit应用程序预先配置成独立运行模式。为了把节点加入现有的集群中,你需要做的是停止应用程序,把节点
重置为原始状态。这样节点就准备好加入集群了。如果你使用 rabbitmqctl stop 命令的话,就会把应用程序和节点同时关闭。这时候如果运行 rabbitmq-server,由于
独立运行模式的关系,又会迫使你把应用程序和节点同时启动起来。另外还有一点是,你会在同一个节点上运行除了rabbitMQ之外的其他erlang应用程序,这使得停止整个节点
是不可取的。
//只停止rabbitmq
rabbitmqctl stop_app
3.1.4 rabbit 配置文件
rabbit 配置文件在 : /etc/rabbitmq/rabbitmq.config
本质上是原始的erlang 数据结构.
mnesia 指的是Mnesia数据库配置选项
rabbit 指的是RabbitMQ特定的配置选项,每个选项都可以表达为这种形式: {[option_name],[option_value]}
rabbitMQ中的每个队列,交换器和绑定的元数据(除了消息的内容)都是保存到Mnesia的。Mnesia是内建在erlang的非sql型数据库。
Rabbit配置选项:
{tcp_listeners,[{ip,端口}]} //定义了rabbitMQ应该监听的肥ssl加密通信的ip地址和端口
{ssl_listeners,[{ip,端口}]} //定义了rabbitMQ应该监听的ssl加密通信的ip地址和端口
{ssl_options,[{键,值}]} //指定了ssl相关的选项
{vm_memory_high_watermark, 0.4} // 控制rabbit允许消耗的内容。它以十进制数值的形式明确了rabbit允许使用的安装内存的百分比(0.4=40%)
3.2 请求许可
rabbitmq 权限工作原理:用户可以为连接到rabbitMQ主机的应用程序设置不同级别的权限(读,写和/或配置)。
rabbit权限系统一个好的地方在于单个用户可以跨越多个vhost进行授权。当应用程序需要跨越多个安全域进行通信时(使用虚拟机进行隔离),
这会极大的方便访问控制的管理。
3.2.1 管理用户
在rabbit中,用户是访问控制的基本单元。针对一到多个vhost,其可以被赋予不同级别的访问权限,并使用标准的用户名/密码来认证用户。
rabbitmqctl list_users //列出当前用户
rabbitmqctl add_user test 123456 // 添加用户名test,密码为123456
rabbitmqctl delete_user test //删除用户
rabbitmqctl change_password test 123456 // 更改用户test的密码
3.2.2 rabbit的权限系统
从1.6.0版本开始,rabbitMQ实现了一套访问控制列表(ACL)风格的权限系统。在这以前,用户只能针对整个vhost进行授权或拒绝访问(对于已授权
的vhost,用户可以做任何事情)。新的授权系统允许大量细粒度控制,同时可以授予用户读,写和配置权限。那么这3者之间有什么差异?
1.读 --- 有关消费消息的任何操作,包括'清楚'整个队列(同样需要绑定操作的成功)
2.写 --- 发布消息(同样需要绑定操作的成功)
3.配置 --- 队列和交换器的创建和删除
每一条访问控制条目由以下4个部分组成:
1.被授予访问权限的用户
2.权限控制应用的vhost
3.需要授予的读/写/配置权限的组合
4.权限范围---权限控制仅应用于客户端命名的队列/交换器呢,还是仅用于服务器端命名的队列/交换器?亦或者都有?客户端吗命名意味着你的应用程序设置了
交换器/队列的名称;服务器端命名意味着你的应用程序不提供名字而是让服务器随机指派。
谨记:访问控制条目是无法跨越vhost的。举例来说,如果你想要给用户 cashing-tier 在 vhost oak 和 vhost sycamore 上赋予相同的权限,那么你必须
创建两份相同的控制条目(每一个vhost一份)。
权限设置:
rabbitmqctl set_permissions -p vhost_name 用户名 配置 写 读
//如,rabbitmqctl set_permissions -p sycamore cashing-tier ".*" ".*" ".*" --- ".*"意味着匹配任何队列或者交换器。
//rabbitmqctl set_permissions -p oak cashing-tier "" "checks-.*" ".*"
".*" 匹配任何队列和交换器
"checks-.*" 只匹配名称以 'checks-' 开头的队列和交换器
"" 不匹配队列和交换器(这就是如何对用户拒绝指定的权限)
//查看权限
rabbitmqctl list_permissions -p vhost_name
//清除权限
rabbitmqctl clear_permissions -p vhost_name 用户名
//查看用户在rabbit服务器上所有vhost的
rabbitmqctl list_user_permissions 用户名
3.3 检查
1.查看队列信息
rabbitmqctl list_queues [-p vhostpath] [queueinfoitem ...] //列出某个vhost下的队列和消息数,默认 /, 还可以列出队列信息
rabbitmqctl list_queues name messages consumers memory //列出名字,消息数,消费者数目,内存
rabbitmqctl list_queues name durable auto_delete //查看队列声明时的属性
2.查看交换器和绑定
rabbitmqctl list_exchanges [-p vhostpath] [exchangeinfoitem ...] //查看交换器信息, 返回交换器名称和类型
你会发现若干个交换器早已经声明好了,例如 amq.topic, amq.direct和 amq.fanout。AMQP规范里对这些交换器有规定。
如果你仔细观察结果的底部,你会发现只有一个direct类型二没有交换器名称。这就是我们之前提到过的匿名交换器,每个队列默认都会
绑定到该交换器。
rabbitmqctl list_exchanges name type durable auto_delete
3.查看绑定信息
rabbitmqctl list_bindings [-p vhostpath] [bindinginfoitem ...]
该命令不接收除 -p 以外的参数。结果由若干行组成,每行包含了交换器名称,队列名称,路由键和参数。最开始的三行非常特殊,好像缺失了什么。。。
那又是匿名交换器的关系。你也可以看到 logs-exchanges(topic 类型交换器)绑定了3个队列。第一个队列 alllogs,通过使用 # 路由键(通配符)进行绑定。
另外两个队列分别使用 *.msg-inbox 和 error.msg-inbox 作为路由键进行绑定。
3.3.2 理解rabbit日志
轮换日志
rabbitmqctl rotate_logs suffix //rabbitmqctl rotate_logs .1
ll /var/log/rabbitmq/rabbit@* //查看日志
通过AMQP实时访问日志:
如何通过AMQP获得实时日志信息。rabbitmqctl list_exchanges 会看到 amq.rabbitmq.log 的 topic 交换器。
rabbit 把日志信息发布到该交换器上,并以验证级别作为路由键---error,warning和info。
3.4 修复rabbit:疑难解答
rabbitmqctl 命令的工作原理:rabbitmqctl 会启动erlang节点,并从那里使用erlang分布式系统尝试连接rabbit节点。
要完成这项工作,你需要两样东西:合适的erlang cookie 和 合适的节点名称。
1.erlang cookie
那什么是 erlang cookie 呢? erlang 节点通过交换作为秘密令牌的 erlang cookie以获得认证。由于你一连接到远程节点后,就能执行命令,
因此有必要确保该节点是可信的。
erlang将令牌存储在名为 .erlang.cookie的文件。该文件通常位于用户的 home 目录下。
cat ~/.erlang.cookie // 查看
为了能让 rabbitmqctl 连接 rabbit 节点,因此需要共享相同的 cookie。如果运行rabbit和执行 rabbitmqctl 命令的是同一个用户,
那么你不会又任何问题。但是在产品环境中,你看你会想要创建 rabbitmq 用户,并以该用户的身份运行服务器。这意味着你必须和 rabbitmq 用户
共享cookie,或者你切换到 rabbitmq 才能成功执行 rabbitmqctl。
2.erlang 节点
当你启动erlang节点时,你可以给它2个互斥的节点名选项,name和sname。节点名可长可短,这也是sname种 s(hort)的含义。如果用长名启动节点,则
它会像 rabbit@hostname.network.tld 这样。如果你用短名字的话,它就会像 rabbit@hostname 这样。后者是启动 rabbit 的默认方式。当你想让
rabbitmqctl 能连上 rabbit 时,你必须使得这些参数2边都能匹配。
3.Mnesia 和主机名
rabbit 使用 Mnesia 存储队列,交换器,绑定等信息。rabbit启动时做的一件事就是启动mnesia数据库。由于这是服务器正常运行的关键一步,因此如果
mnesia启动事变,那么rabbit也会失败。
导致mnesia 启动失败的原因大致有二:
1.第一个也是最常见的是 MNESIA_BASE 目录的权限问题。运行rabbit服务器的用户需要对该文件夹的写权限。
2.另外一个是,Mnesia 读取表格失败了。如果主机名更改了,或者是服务器运行在集群模式下,无法在启动的时候连接到其他节点,这些都会导致失败。
为什么需要关注主机名呢?mnesia会基于机器的主机名创建数据库schema。如果你列出 MNESIA_BASE 文件夹的内容,你就会看到一个文件夹是rabbit@hostname。
如果由于网络重新配置的原因,主机名修改了,那么mnesia久无法载入旧的schema。同时请谨记rabbitmq使用 rabbit这个单词作为节点名。如果你使用erlang sname
选项修改了它,mnesia又会遇到同样的问题。
基于相同的原因,你会发现如果你重命名了 rabbit@hostname文件夹,那么mnesia将无法找到旧的数据库文件。你会重新创建rabbit@hostname文件夹并启动数据库。
记住:你仍然可以在你重命名的文件夹下找到旧的数据库文件。
4.erlang故障排除技巧
//用短名字启动 rabbitMQ
erl -sname test //用test作为节点名字启动了erlang节点
//找出节点名字
node() .
//查看你的机器运行了哪些节点
net_adm:names() . //输出,{ok,[{"rabbit",25672},{"test",36678}]}
net_adm模块调用了 names() 函数。如你所见,rabbit正运行在你的机器上。它使用 rabbit 作为节点名称并使用 25672 端口。那并不是你从AMQP
客户端用来连接到 rabbitMQ的端口。这是怎么回事?这就需要另外一位角色登场了:erlang port mapper daemon(epmd)。当你启动一个分布式 erlang
节点时,它会启用 epmd 进程进行注册,提供 OS 内核分配的地址和端口。之后当另一个 erlang 节点启动时,它会做同样的事情。最后,如果后者想要连接
第一个节点的话,它会查阅 epmd 以获得节点地址。通过这种方式,你就不需要自己追踪信息了。然后那个端口号(示例中的 25672)是由 OS 分配给运行的rabbit
的 erlang VM的。
//尝试建立连接
net_adm:ping('rabbit@php-server') . // pong 表明成功了; pang 表明无法连接到该几点。记住为了使一切工作正常,你必须共享同样的erlang cookie。
nodes() . // 会展示你连接上的节点列表
rpc:call('test@php-server',erlang,system_info,[proces_count]) .
//这里你使用了erlang的 rpc 模块在 test@php-server 节点调用了一个函数。你使用 erlang:system_info 函数获得该节点上erlang 进程的数目。你可以使用该
函数监控rabbitmq系统的健康情况。如果 process_count 超过了 process_limit 的限制,你的服务器就会崩溃。
通过使用 rpc:call,同时提供节点,模块,函数和参数作为入参,你可以在远程 rabbit 上执行其他函数以获得不同的信息。
//打印关于Mnesia的若干信息。
rcp:call('test@php-server',mnesia,info,[]) .
//退出
q() .
3.运行和管理Rabbit
3.2 请求许可
3.3 检查
3.3.2 理解rabbit日志
3.4 修复rabbit:疑难解答