RabbitMQ研究&部署

阅读 132

2023-04-13

一、RabbitMQ简介

RabbitMQ是使用Erlang语言来开发的,并且基于AMQP协议实现。

1.1 RabbitMQ基本概念

RabbitMQ研究&部署_RabbitMQ

AMQP:Advanced Message Queue,高级消息队列协议。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。

由于RabbitMQ 是 AMQP 协议的一个开源实现,所以其内部实际上也是 AMQP 中的基本概念。

  • Broker:接收和分发消息的应用,RabbitMQ Server就是Message Broker
  • Connection:连接,应用程序与Server的网络连接。
  • Channel:因为对于操作系统来说建立和销毁 TCP 链接都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。如果应用程序支持多线程,通常每个线程建立单独的channel进行通信,AMQP线程包含了channel id帮助客户端和broker识别channel,因此channel之间是完全隔离的。Channel作为轻量级的Connection极大减少了操作系统建立TCP 连接的开销
  • Message:消息,应用程序和服务器之间传送的数据,消息可以非常简单,也可以很复杂。有Properties和Body组成。Properties为外包装,可以对消息进行修饰,比如消息的优先级、延迟等高级特性;Body就是消息体内容。
  • Virtual Host:虚拟主机,基于多租户和安全因素设计。类似于网络中的namespace概念,做资源隔离用。当多个不同的用户使用同一个RabbitMQ Server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue
  • Publisher:消息的生产者,也是一个向交换器发布消息的客户端应用程序。
  • Consumer:消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
  • Exchange:交换器,message到达broker的首站,按照路由规则将消息路由到一个或者多个队列。如果路由不到,或者返回给生产者,或者直接丢弃。RabbitMQ的交换器类型有direct、topic、fanout、headers四种。
  • Binding:绑定,交换器和消息队列之间的虚拟连接,绑定中可以包含一个或者多个RoutingKey。Binding信息保存在exchange中的查询表中,作为message的分发依据
  • RoutingKey:路由键,生产者将消息发送给交换器的时候,会发送一个RoutingKey,用来指定路由规则,这样交换器就知道把消息发送到哪个队列。路由键通常为一个“.”分割的字符串,例如“com.rabbitmq”。
  • Queue:消息队列,用来保存消息,供消费者消费。

1.2 RabbitMQ的优缺点

1.2.1 优点

  • 基于erlang语言开发,高并发,支持分布式
  • 轻量级、健壮、稳定、易用、跨平台、支持多种语言
  • 开源提供的管理界面简单易用

1.2.2 缺点

  • Erlang开发,很难看懂源码,基本职能依赖于开源社区的快速维护和修复bug,不利于做二次开发
  • RabbitMQ的吞吐量偏低,只有每秒几万的级别,遇到像双十一这样的高并发场景,很容易到达性能的瓶颈。

1.3 RabbitMQ中的生产者/消费者示例

RabbitMQ研究&部署_RabbitMQ_02

生产者发送消息到broker server(RabbitMQ),在broker内部,用户创建Exchange和Queue,通过Binding规则将二者联系在一起。Exchange根据不同的路由规则将消息分发到不同的队列,等待消费者取走。

1.4 Exchange的各种类型

1.4.1 Direct Exchange

它是Exchange的默认类型。所有发送到 Direct Exchange 的消息被转发到 RouteKey 中指定的 Queue。
      Direct 模式,可以使用 rabbitMQ 自带的 Exchange:default Exchange。所以不需要将 Exchange 进行任何绑定(binding)操作 。消息传递时,RouteKey 必须完全匹配,才会被队列接收,否则该消息会被抛弃。

RabbitMQ研究&部署_RabbitMQ_03

1.4.2 Topic Exchange

是指发送到 Topic Exchange 的消息被转发到所有关心的 Routing key 中指定 topic 的 Queue 上。Exchange 将 routing key 和某 Topic 进行模糊匹配,此时队列需要绑定一个 Topic。所谓模糊匹配就是可以使用通配符,“#”可以匹配一个或多个词,“*”只匹配一个词。比如“log.#”可以匹配“log.info.test”, "log.*"就只能匹配 log.error。
      同样,如果Exchange没有发现能够与 RouteKey 匹配的 Queue,则会抛弃此消息。

RabbitMQ研究&部署_RabbitMQ_04

1.4.3 Fanout Exchange

无需处理路由键,只需简单的将队列绑定到交换机上。类似于广播、群发,发送到该交换机上的消息都会被发送到与该交换机绑定的所有队列上。Fanout 转发是最快的。

RabbitMQ研究&部署_RabbitMQ_05

      总而言之:Direct change是严格意义上的匹配,routing key 与 binding key 完全一样; Fanout Exchange 是完全不关心你的routing key,向所有绑定的queue 全部发送;这是两个极端,那么Toptic Exchange 就相对Direct change宽松一些,它的消息投递取决于模糊匹配的结果。

1.4.4 Headers Exchange

该类型的交换器不依赖路由规则来路由消息,而是根据消息内容中的headers属性进行匹配。实际中并不常用。

二、RabbitMQ单机部署

2.1 安装RabbitMQ

官网下载地址:https://rabbitmq.com/download.html

#更新安装源
apt-get -y update
#安装依赖包
apt-get -y install curl gnupg apt-transport-https
#导入RabbitMQ的密钥
curl -1sLf "https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA" | sudo gpg --dearmor | sudo tee /usr/share/keyrings/com.rabbitmq.team.gpg > /dev/null
#导入erlang的密钥
curl -1sLf https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/gpg.E495BB49CC4BBE5B.key | sudo gpg --dearmor | sudo tee /usr/share/keyrings/io.cloudsmith.rabbitmq.E495BB49CC4BBE5B.gpg > /dev/null
#添加RabbitMQ存储库
curl -1sLf https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/gpg.9F4587F226208342.key | sudo gpg --dearmor | sudo tee /usr/share/keyrings/io.cloudsmith.rabbitmq.9F4587F226208342.gpg > /dev/null
#添加源文件
vim /etc/apt/sources.list.d/rabbitmq.list
## Provides modern Erlang/OTP releases
##
deb [signed-by=/usr/share/keyrings/io.cloudsmith.rabbitmq.E495BB49CC4BBE5B.gpg] https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/deb/ubuntu bionic main
deb-src [signed-by=/usr/share/keyrings/io.cloudsmith.rabbitmq.E495BB49CC4BBE5B.gpg] https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/deb/ubuntu bionic main
 
## Provides RabbitMQ
##
deb [signed-by=/usr/share/keyrings/io.cloudsmith.rabbitmq.9F4587F226208342.gpg] https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/deb/ubuntu bionic main
deb-src [signed-by=/usr/share/keyrings/io.cloudsmith.rabbitmq.9F4587F226208342.gpg] https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server/deb/ubuntu bionic main
 
#更新安装源
apt-get -y update
#安装erlang
apt-get install -y erlang-base erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssl erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl
#查看可以安装的版本
apt-cache madison rabbitmq-server
#安装较新版本的RabbitMQ
apt-get -y install rabbitmq-server=3.11.13-1

安装erlang遇到如下问题:
erlang-crypto : Depends: libssl1.1 (>= 1.1.1) but it is not installable
解决方案:
wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb
dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb

2.2 RabbitMQ插件管理

#开启web界面管理插件
rabbitmq-plugins enable rabbitmq_management

其中,5672是客户端访问的端口,15672是web管理端口,25672是集群管理端口。

2.3 登录web管理界面&RabbitMQ相关命令

RabbitMQ从3.3.0版本开始禁止使用guest/guest权限通过除localhost之外的访问,具体报错如下:

RabbitMQ研究&部署_RabbitMQ_06

这里需要先添加用户,再将用户设置为管理员权限。相关命令如下:

#添加用户(eg:jack/123456)
rabbitmqctl add_user jack 123456
为用户设置超级管理员权限
rabbitmqctl set_user_tags jack administrator
#查看用户列表
rabbitmqctl list_users
#更改用户密码
rabbitmqctl change_password jack xxx
#删除用户
rabbitmqctl delete_user jack
#创建vhost
rabbitmqctl add_vhost xxx
#列出所有vhost
rabbitmqctl list_vhosts
#列出所有队列
rabbitmqctl list_queues
#删除指定vhost
rabbitmqctl delete_vhost xxx
#设置jack用户对指定的vhost有读写权限,三个点为配置正则、读和写
rabbitmqctl set_permissions -p xxx jack ".*" ".*" ".*"

现在用jack/123456就能登录RabbitMQ的web管理界面了。

2.4 RabbitMQ的用户角色

分为5类:

  • None(其它):无法登录管理控制台,通常就是普通的生产者和消费者
  • management(普通管理者):仅可登陆管理控制台(启用management plugin的情况下),无法看到节点信息,也无法对策略进行管理
  • policymaker(策略制定者):可登陆管理控制台(启用management plugin的情况下),同时可以对policy进行管理。但无法查看节点的相关信息
  • monitoring(监控者):可登陆管理控制台(启用management plugin的情况下),同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
  • administrator(超级管理员):可登陆管理控制台(启用management plugin的情况下),可查看所有的信息,并且可以对用户,策略(policy)进行操作

三、RabbitMQ集群部署

3.1 RabbitMQ集群模式介绍

RabbitMQ集群模式分为两种模式:普通模式和镜像模式

3.1.1 普通模式

默认的集群模式。创建队列之后,如果没有其它的数据同步方式,消息实体只存在于其中一个节点 A(或者 B),A 和 B 两个节点仅有相同的元数据,即队列的结构。当消息进入 A 节点的 Queue 后,consumer 从 B 节点消费时,RabbitMQ 会临时在 A、B 间进行消息传输,把 A 中的消息实体取出并经过 B 发送给 consumer。所以 consumer 可连接每一个节点,从中取消息。问题在于,当 A 节点故障后,B 节点无法取到 A 节点中还未消费的消息实体。如果做了消息持久化,那么得等 A 节点恢复,然后才可被消费;如果没有持久化的话,就会产生消息丢失的现象。

3.1.2 镜像模式

将需要消费的队列变为镜像队列,存在于多个节点,这样就可以实现 RabbitMQ 的高可用性。作用就是消息实体会主动在镜像节点之间实现同步,而不是像普通模式那样,在 consumer 消费数据时临时读取。缺点就是,集群内部的同步通讯会占用大量的网络带宽。适用于对可靠性要求较高的场合。

集群中有两种节点类型:

  • 内存节点:只将数据保存到内存
  • 磁盘节点:保存数据到内存和磁盘

RabbitMQ集群建议至少有一个磁盘节点,用于数据备份。其他节点可以是内存节点,当节点加入或者离开集群时,必须要将该变更通知到至少一个磁盘节点。如果集群中唯一的一个磁盘节点崩溃的话,集群仍然可以保持运行,但是无法进行其他操作,直到节点恢复。

3.2 安装集群版RabbitMQ

集群使用三台服务器,IP地址为192.168.131.11~13

3.2.1 配置hosts解析

192.168.131.11 node1
192.168.131.12 node2
192.168.131.13 node3

3.2.2 各个服务器安装RabbitMQ

安装步骤与上述RabbitMQ单机部署相同。

3.2.3 创建RabbitMQ集群

RabbitMQ集群是依赖于erlang集群来工作的,所以需要先构建erlang的集群环境。Erlang集群中的各节点是通过一个cookie实现的,该cookie存放在/var/lib/rabbitmq/.erlang.cookie中,文件权限为400,需要在各个节点保持一致,否则无法通信。

#三台机器停止RabbitMQ
systemctl stop rabbitmq-server
#node1机器同步cookie到另外两台机器
scp -r /var/lib/rabbitmq/.erlang.cookie 192.168.131.12:/var/lib/rabbitmq/.erlang.cookie
scp -r /var/lib/rabbitmq/.erlang.cookie 192.168.131.13:/var/lib/rabbitmq/.erlang.cookie
#三台机器再重启RabbitMQ
systemctl start rabbitmq-server
 
##node2和node3节点作为内存节点加入node1集群。以下操作在node2和node3节点执行
#关闭应用。注意:默认节点类型是磁盘节点,如果是内存节点的话,需要加--ram参数
rabbitmqctl stop_app
#清空元数据
rabbitmqctl reset
#--ram是以内存节点的方式加入集群
rabbitmqctl join_cluster --ram rabbit@node1
#启动应用
rabbitmqctl start_app
#查看集群状态(任意节点均可执行)
rabbitmqctl cluster_status

3.2.4 将集群设置为镜像模式

#在任意一个节点执行如下命令
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'

参数说明:
• ha-all:为策略名称
• ^:为匹配符,只有一个 ^ 代表匹配所有。Eg:^abc为匹配名称为abc的exchanges或者queue
• ha-mode:为匹配类型,分为 3 种模式:
(1)all--所有(所有的 queue)
(2)exctly--部分(需配置ha-params参数,此参数为int类型比如3,众多集群中的随机3台机器)
(3)nodes--指定(需配置ha-params参数,此参数为数组类型。比如["rabbit@M","rabbit@N"]这样指定为M与N这2台机器)

3.2.5 web界面验证集群状态

如果RabbitMQ服务器不启用web插件,会在web节点提示节点统计信息不可用。开启web插件后的集群状态如下:

RabbitMQ研究&部署_RabbitMQ_07

精彩评论(0)

0 0 举报