RabbitMQ集群部署过程记录

0.前言

目前手上的一个中长期任务就是消息队列的升级,继RocketMQ之后,开始对RabbitMQ进行研究,首先当然还是简单的原理了解加集群环境搭建。

1.集群原理

RabbitMQ 是一个由 Erlang 语言开发的 AMQP (Advanced Message Queue,高级消息队列协议)的开源实现,因为Erlang自带集群特性,因此RabbitMQ的集群也是基于此实现的。RabbitMQ的集群有两种模式,分别为默认集群模式和镜像模式。

  • 默认模式:消息实体只存在于一个节点上,其它节点仅存储对应的元数据,当客户端连接到未存储消息实体的节点时,RabbitMQ会根据元数据从对应节点取得消息后再转发给客户端。这样做有一个显而易见的问题是,当某个节点宕机时,无论该节点是否有做消息持久化,存储在该节点的未消费消息都会暂时或者永久无法被消费。

    元数据复制.jpg

  • 镜像模式:镜像模式顾名思义就是将一个节点存储的消息在镜像节点上进行主动同步,以防止单个节点宕机造成的问题。当然这种模式的消息高可靠性也是建立在性能损耗上的,适用于对消息可靠性要求特别高的场合,如订单类消息。

本文后面的讲解都会基于默认的集群模式来进行。

1.1集群元数据的同步

当在集群中声明队列、交换器、绑定的时候,这些操作会直到所有集群节点都成功提交元数据变更后才返回。RabbitMQ集群会始终同步四种类型的内部元数据(类似索引):

  • a.队列元数据:队列名称和它的属性;
  • b.交换器元数据:交换器名称、类型和属性;
  • c.绑定元数据:一张简单的表格展示了如何将消息路由到队列;
  • d.vhost元数据:为vhost内的队列、交换器和绑定提供命名空间和安全属性;
    因此,当用户访问其中任何一个RabbitMQ节点时,通过rabbitmqctl查询到的queue/user/exchange/vhost等信息都是相同的。
1.2内存节点和磁盘节点

集群中的节点有内存节点和磁盘节点两种类型,内存节点虽然不写入磁盘,但是它的执行比磁盘节点要好。内存节点可以提供出色的性能,磁盘节点能保障配置信息在节点重启后仍然可用,那集群中如何平衡这两者呢?
RabbitMQ 只要求集群中至少有一个磁盘节点,所有其他节点可以是内存节点,当节点加入火离开集群时,它们必须要将该变更通知到至少一个磁盘节点。如果只有一个磁盘节点,刚好又是该节点崩溃了,那么集群可以继续路由消息,但不能创建队列、创建交换器、创建绑定、添加用户、更改权限、添加或删除集群节点。换句话说集群中的唯一磁盘节点崩溃的话,集群仍然可以运行,但知道该节点恢复,否则无法更改任何东西。

2.集群搭建

我的RabbitMQ集群搭建在两台centos6.9服务器上。这里我使用了最简单的通过yum方式安装RabbitMQ,由于RabbitMQ依赖于Erlang环境,通过yum的方式安装会自动处理依赖的程序,所以会自动安装好Erlang,对于不熟悉Erlang的人来说省去了很多麻烦。

2.1单机安装

首先看一下yum源中的RabbitMQ版本,通过下述命令查询

yum list | grep rabbitmq

查到最新的安装包为rabbitmq-server.noarch,版本为3.1.5-1.el6,虽然不是最新的,但暂时应该够用了,通过以下命令安装

yum -y install rabbitmq-server.noarch

安装完成后首先通过erl -v命令检查Erlang环境是否已安装

Erlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.8.5  (abort with ^G)

1>

可以看到R14B04版本已经安装完成,这也是目前yum源自带的最高版本了,如果要安装更高版本的RabbitMQ这个Erlang版本是肯定不够的,就需要再另外自行安装更高版本Erlang。这里顺带提一下,要退出Erlang的控制台需要输入halt().命令,否则只能通过ctrl+z强行退出。

2.2服务启动

首先打开服务

chkconfig rabbitmq-server on

启动RabbitMQ

service rabbitmq-server start

查看状态

rabbitmqctl status

看到如下信息则证明RabbitMQ已正常启动

Status of node rabbit@host05 ...
[{pid,8927},
 {running_applications,[{rabbit,"RabbitMQ","3.1.5"},
                        {os_mon,"CPO  CXC 138 46","2.2.7"},
                        {mnesia,"MNESIA  CXC 138 12","4.5"},
                        {xmerl,"XML parser","1.2.10"},
                        {sasl,"SASL  CXC 138 11","2.1.10"},
                        {stdlib,"ERTS  CXC 138 10","1.17.5"},
                        {kernel,"ERTS  CXC 138 10","2.14.5"}]},
 {os,{unix,linux}},
 {erlang_version,"Erlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:30] [kernel-poll:true]\n"},
 {memory,[{total,27533368},
          {connection_procs,2704},
          {queue_procs,5408},
          {plugins,0},
          {other_proc,9049416},
          {mnesia,61424},
          {mgmt_db,0},
          {msg_index,34160},
          {other_ets,798568},
          {binary,5312},
          {code,14419209},
          {atom,1355273},
          {other_system,1801894}]},
 {vm_memory_high_watermark,0.4},
 {vm_memory_limit,1607422771},
 {disk_free_limit,1000000000},
 {disk_free,18049622016},
 {file_descriptors,[{total_limit,924},
                    {total_used,3},
                    {sockets_limit,829},
                    {sockets_used,1}]},
 {processes,[{limit,1048576},{used,124}]},
 {run_queue,0},
 {uptime,74460}]
...done.
2.3加入集群

首先有两个点需要注意:

  1. RabbitMQ节点的命名一般是rabbit@服务器host,因此需要在/etc/hosts文件中配置对应的ip和hostname,防止host无法解析的情况;
  2. RabbitMQ集群是基于Erlang的集群的,因此需要保证Erlang节点间的互通。Erlang的节点互通需要节点之间有相同的cookie,因此将节点2的/var/lib/rabbitmq/.erlang.cookie修改为和节点1一样,同时为保证cookie文件的权限,需要执行以下命令:
chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie

chmod 400 /var/lib/rabbitmq/.erlang.cookie

接着将节点2加入到节点1的集群中,首先需要停止节点2上的应用(不是停止Erlang节点),否则会报以下错误

Clustering node rabbit@host05 with rabbit@host04 ...
Error: mnesia_unexpectedly_running

在节点2上运行以下命令

rabbitmqctl  stop_app

清楚节点2上的队列信息

rabbitmqctl reset

加入集群

rabbitmqctl join_cluster rabbit@节点1

如果要以内存节点模式加入则执行以下命令

rabbitmqctl join_cluster --ram rabbit@节点1

重新启动节点2上的应用

rabbitmqctl  start_app

查看集群状态

rabbitmqctl cluster_status

看到如下显示证明集群建立成功

Cluster status of node rabbit@host04 ...
[{nodes,[{disc,[rabbit@host04,rabbit@host05]}]},
 {running_nodes,[rabbit@host05,rabbit@host04]},
 {partitions,[]}]
...done.

3.管理页面

3.1页面启动
rabbitmq-plugins enable rabbitmq_management

RabbitMQ很贴心的自带管理页面,该页面属于一种插件功能,通过上述命令启动,启动后默认通过http://ip:15672登陆访问
这里顺带提一下其它默认的端口:

  • 4369 (epmd)
  • 25672 (Erlang distribution)
  • 5672, 5671 (AMQP 0-9-1 without and with TLS)
  • 15672 (if management plugin is enabled)
  • 61613, 61614 (if STOMP is enabled)
  • 1883, 8883 (if MQTT is enabled)
3.2创建账号
rabbitmqctl add_user admin admin

登录管理页面需要创建账号,如上所示命令用于创建admin/admin账号

3.3赋予角色
rabbitmqctl set_user_tags admin administrator

上述命令将administrator角色赋给admin用户,至此就可以通过admin/admin账号进行登陆了

管理页面.png
3.4其它命令

其它常用用户管理命令如下:

  • list_users,用户列表
  • add_user {username} {password},添加用户
  • delete_user {username},删除用户
  • change_password {username} {newpassword},修改密码
  • clear_password {username},删除密码,密码删除后就不能访问了
  • authenticate_user {username} {password},用户认证
  • set_user_tags {username} {tag ...},为用户设置角色,tag可以是0个、一个、或多个

常用权限管理命令如下:

  • list_vhosts [vhostinfoitem ...],获取vhosts列表
  • add_vhost {vhost}, eg:rabbitmqctl add_vhost test
  • delete_vhost {vhost}
  • set_permissions [-p vhost] {user} {conf} {write} {read},给用户分在对应的vhost上分配相应的权限。eg:rabbitmqctl set_permissions -p /myvhost chris "^chris-." "." ".*",这条指令,给用户chris在myvhost分配了权限,权限包括:以"chris-"开头的全部资源的配置权限,和所有资源的读写权限
  • clear_permissions [-p vhost] {username},清除权限
  • list_permissions [-p vhost],vhost权限分配列表
  • list_user_permissions {username},user权限列表

4.遇到的问题

服务无法启动,并报了如下的错误:

BOOT FAILED
===========

Error description:
   {error,{cannot_log_to_file,"/var/log/rabbitmq/rabbit@host04.log",
                              {error,eacces}}}

Log files (may contain more information):
   /var/log/rabbitmq/rabbit@host04.log
   /var/log/rabbitmq/rabbit@host04-sasl.log

Stack trace:
   [{rabbit,ensure_working_log_handler,5},
    {rabbit,ensure_working_log_handlers,0},
    {rabbit,'-boot/0-fun-1-',0},
    {rabbit,start_it,1},
    {init,start_it,1},
    {init,start_em,1}]

{"init terminating in do_boot",{rabbit,failure_during_boot,{error,{cannot_log_to_file,"/var/log/rabbitmq/rabbit@host04.log",{error,eacces}}}}}

Crash dump was written to: erl_crash.dump
init terminating in do_boot ()

查阅资料发现是rabbitmq没有/var/log/rabbitmq目录的权限造成的,使用chown -R rabbitmq:rabbitmq /var/log/rabbitmq/赋予权限后再次启动,问题解决,但问题造成的原因未知。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • RabbitMQ 原理介绍及安装部署 标签:RabbitMQ 安装 简介 RabbitMQ 是一个用 Erlang...
    神仙CGod阅读 8,551评论 0 60
  • 关于消息队列,从前年开始断断续续看了些资料,想写很久了,但一直没腾出空,近来分别碰到几个朋友聊这块的技术选型,是时...
    中v中阅读 1,967评论 0 20
  • RabbitMQ采用Erlang编写,需安装语言库才能运行RabbitMQ代理服务器。AMQP:高级消息队列协议。...
    JAVA觅音阁阅读 3,586评论 0 7
  • 关于消息队列,从前年开始断断续续看了些资料,想写很久了,但一直没腾出空,近来分别碰到几个朋友聊这块的技术选型,是时...
    预流阅读 584,412评论 51 785
  • 整体架构 部署步骤 基于 Docker 基本概念内存节点只保存状态到内存,例外情况是:持久的 queue 的内容将...
    mvictor阅读 12,746评论 5 30