引言
你是否遇到过两个(多个)系统间需要通过定时任务来同步某些数据?你是否在为异构系统的不同进程间相互调用、通讯的问题而苦恼、挣扎?如果是,那么恭喜你,消息服务让你可以很轻松地解决这些问题。
消息服务擅长于解决多系统、异构系统间的数据交换(消息通知/通讯)问题,你也可以把它用于系统间服务的相互调用(RPC)。本文将要介绍的RabbitMQ就是当前最主流的消息中间件之一。本文仅关注高可用安装和使用,后续篇章持续关注
下载
由于RabbitMQ是基于Erlang语言开发,所以在安装RabbitMQ之前,需要先安装Erlang。好在RabbitMQ官网已经为我们提供了Erlang的安装包
本人使用的操作系统为:CentOS7
下载的Erlang安装包为:erlang-19.0.4-1.el7.centos.x86_64.rpm
RabbitMQ下载地址:https://www.rabbitmq.com/download.html
下载的RabbitMQ安装包为:rabbitmq-server-3.6.8-1.el7.noarch.rpm
安装
将下载的两个文件上传到/usr/local目录,先安装Erlang
yum install erlang-19.0.4-1.el7.centos.x86_64.rpm
测试Erlang是否安装成功
出现以下信息则表示安装成功:
Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 8.0.3
安装RabbitMQ
yum
install
rabbitmq-server-3
.6
.8-1
.el7
.noarch
.rpm
运行RabbitMQ
cd
/usr/sbin
./rabbitmq-server start
出现以下信息,则表示启动成功:
RabbitMQ 3.6.8. Copyright (C) 2007-2016 Pivotal Software, Inc.
#
#
#
#
#
Starting broker...
completed with 0 plugins.
后台启动可使用:
./rabbitmq-
server
-detached
插件安装
查看目前RabbitMQ已安装的插件
cd
/usr/sbin
./rabbitmq-plugins list
安装web管理端
./rabbitmq-plugins
enable
rabbitmq_management
安装成功后,启动MQ
通过浏览器访问地址:http://192.168.120.129:15672/#/
由于guest用户被限制,只能通过localhost访问,因此我们需要新建一个用户,并授予管理员权限。
新建一个用户名为admin,密码为admin的用户,并授予管理员(administrator)权限
./rabbitmqctl add_user admin admin
./rabbitmqctl set_user_tags admin administrator
安装mqtt
./rabbitmq-plugins
enable
rabbitmq_mqtt
安装websocket
./rabbitmq-plugins
enable
rabbitmq_web_stomp
./rabbitmq-plugins
enable
rabbitmq_web_stomp_examples
配置
如果需要修改RabbitMQ的默认配置,先查找配置文件样例位置
find
/ -name
"rabbitmq.config.example"
然后将样例配置复制到制定目录
cp /usr/share/doc/rabbitmq-server
-3.6
.8
/rabbitmq.
config
.example /etc/rabbitmq/rabbitmq.
config
修改样例文件,并保存,重启MQ生效。
权限
主要是set_permissions的使用,先看下命令的格式:
set_permissions [-p vhost] {user} {conf} {
write
} {
read
}
首先需要注意以下几点的理解:
1.这里的权限,只是针对一般用户的访问权限,注意和角色的区分。举个例子来说,非管理用户(普通用户),角色设置为none,然后在这里配置conf、write、read的权限。
2.conf、write、read采用正则表达式,这里的正则主要是针对exchange和queue。主要2种特殊的表达式:
^$:表示完全不匹配(即没有权限)
.*:表示匹配所有(即所有权限)
如果使用RabbitMQ作为消息推送服务,需要授予用户只读访问Stomp主题权限,同时授予另一个用户对同一主题的读写访问权限。
这样的话主题订阅者就不能发布消息,从而解决安全性问题。
但是如果直接这样授权:
rabbitmqctl set_permissions
read
-only-user
'.*'
'^$'
'.*'
会报如下错误:
ERROR
message
:access_refused content-
type
:text/plain version:
1.0
,
1.1
,
1.2
content-length:
114
ACCESS_REFUSED - access
to
queue
'stomp-subscription-APK3zkvXFqxvSiZ9ztmxYQ'
in
vhost
'/'
refused
for
user
'test'
Whoops! Lost connection
to
ws:
这样配置存在一个问题,将阻止任何写入,阻止任何写入将导致没有权限连接到RabbitMQ的服务
需要对可读用户权限做如下调整:
rabbitmqctl set_permissions
read
-only-user
'^stomp-subscription.*$'
'^stomp-subscription.*$'
'.*'
集群模式
RabbitMQ集群模式分为两种:普通模式,镜像模式(HA)
普通模式
:默认的集群模式
对于Queue来说,消息实体只存在于其中一个节点,A、B两个节点仅有相同的元数据,即队列结构。
当消息进入A节点的Queue中后,consumer从B节点拉取时,RabbitMQ会临时在A、B间进行消息传输,把A中的消息实体取出并经过B发送给consumer。
所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连A或B,出口总在A,会产生瓶颈。
该模式存在一个问题就是当A节点故障后,B节点无法取到A节点中还未消费的消息实体。
如果做了消息持久化,那么得等A节点恢复,然后才可被消费;如果没有持久化的话,然后就没有然后了……
镜像模式
:把需要的队列做成镜像队列,存在于多个节点,属于RabbitMQ的HA方案
该模式解决了上述问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取。
该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。
所以在对可靠性要求较高的场合中适用。
服务器信息:
我们准备了两台服务器,系统为Centos7,对应的ip跟hostname分别为
192.168.1.242 mq01
192.168.1.243 mq02
在安装好的两台节点服务器中,分别修改/etc/hosts文件,指定mq01,mq02的hosts,如:
192.168.1.242 mq01
192.168.1.243 mq02
注意:hostname文件也要正确,分别是mq01、mq02,如果修改hostname建议在安装rabbitmq前修改。
设置 Erlang Cookie:
Rabbitmq的集群是依赖于erlang的集群来工作的,所以必须先构建起erlang的集群环境。Erlang的集群中各节点是通过一个magic cookie来实现的,这个cookie存放在 /var/lib/rabbitmq/.erlang.cookie 中,文件是400的权限。所以必须保证各节点cookie保持一致,否则节点之间就无法通信。
查看文件权限的命令为:
ls -l
/var/lib/rabbitmq/
.erlang.cookie
这里将 mq01的 /var/lib/rabbitmq/.erlang.cookie文件复制到 mq02,由于这个文件权限是 400,所以需要先修改该文件权限为 777:
chmod
777
/var
/lib/rabbitmq/
.erlang.cookie
使用scp或其他方式将该文件复制到mq02服务器的相同目录,并覆盖。
然后将mq01的 /var/lib/rabbitmq/.erlang.cookie文件权限修改回来
chmod
400
/var
/lib/rabbitmq/
.erlang.cookie
组成集群
重启RabbitMQ服务:
rabbitmqctl
stop
rabbitmq-
server
-detached
将mq02与mq01组成集群:
./rabbitmqctl stop_app
./rabbitmqctl join_cluster rabbit@mq01
./rabbitmqctl
stop
./rabbitmq-
server
-detached
如果要使用内存节点,则可以使用--ram:
rabbitmqctl
join_cluster --ram rabbit
@mq01
查看集群是否配置成功: