1.AMQP简介
AMQP (Advanced Message Queuing Protocol)是一种允许符合要求的客户端应用和消息中间件(messaging middleware broker)进行通信的消息传递协议。消息中间件代理的作用:从发布者接收消息,通过路由规则将消息发送给消费者。
1.1 AMQP 0-9-1模型
首先发布者(publisher)将消息(message)发送给交换机(exchanges),交换机再根据路由规则分发到绑定(bindings)的队列(queues),最后AMQP将消息发送给队列的消费者。队列(queues),交换机(exchanges)和绑定(bindings)统称为AMQP实体(AMQP entities)
1.2 队列(Queues)
队列(Queues)用于存储被消费者(Consumer)消费的消息。生产者把消息发布到交换机上,消息最终到达队列,被消费者接受。队列收到的消息将以轮询的方式发送给消费者,每条消息都只会有一个订阅的消费者。队列的作用
- 队列是AMQP消息通信的基础模块,为消息提供了处所,消息在队列中等待消费者消费
- 队列对于负载均衡是较好方案,只需要一堆消费者,并轮询的方式分配消息即可
队列在声明(declare)后才能被使用。如果一个队列尚不存在,声明一个队列会创建它。如果声明的队列已经存在,并且属性完全相同,那么此次声明不会对原有队列产生任何影响。如果声明中的属性与已存在队列的属性有差异,那么一个错误代码为406的通道级异常就会被抛出。队列的主要属性:
- Name
- Durable(消息代理重启后,队列依旧存在)
- Exclusive(只被一个连接(connection)使用,而且当连接关闭后队列即被删除)
- Auto-delete(当最后一个消费者退订后即被删除)
1.3 绑定(Binding)
绑定(Binding)是交换机(exchange)将消息(message)路由给队列(queue)所需遵循的规则。如果要指示交换机“E”将消息路由给队列“Q”,那么“Q”就需要与“E”进行绑定。绑定操作需要定义一个可选的路由键(routing key)属性给某些类型的交换机。路由键的意义在于从发送给交换机的众多消息中选择出某些消息,将其路由给绑定的队列。 路由键(routing key)决定了交换机将消息分发的到的队列,通过路由键的设置可以决定消息发送给一个或者多个需要的消费者。 拥有了交换机这个中间层,很多由发布者直接到队列难以实现的路由方案能够得以实现,并且避免了应用开发者的许多重复劳动。 如果AMQP的消息无法路由到队列(例如,发送到的交换机没有绑定队列),消息会被就地销毁或者返还给发布者。如何处理取决于发布者设置的消息属性。
1.4 交换机(Exchanges)
交换机是消息发送实体,交换机将消息发送给一个或者零个队列(queue)当中,交换机类型和绑定(bindings)决定了路由算法。AMQP 0-9-1提供了四种交换机类型:
- 直连交换机(Direct exchange)
- 扇形交换机(Fanout exchange)
- 主题交换机(Topic exchange)
- 头交换机(Headers exchange)
在设置交换机时通常会设置几个重要的属性:
- Name:交换机名称
- Durability:持久化,即代理重启后交换机依然存活
- AutoDelete:自动删除,当队列最后一个消息完成对交换机的使用后自动删除交换机
默认交换机(Default Exchange)
默认交换机(default exchange)实际上是一个由消息代理预先声明好的没有名字(名字为空字符串)的直连交换机(direct exchange)。它有一个特殊的属性使得它对于简单应用特别有用处:那就是每个新建队列(queue)都会自动绑定到默认交换机上,绑定的路由键(routing key)名称与队列名称相同。 特点:
- 交换机名字(Name)为空字符串
- 路由键名与队列(queue)名相同
直连交换机(Direct exchange)
直连型交换机(Direct exchange)是最基本的交换机,用于处理单播路由。根据路由键(routing key)将消息发送到对应的队列中。首先将队列绑定到交换机上,同时设置一个路由键,当一个携带该路由键的消息发送到直连交换机时,交换机则把他路由到相同路由键的队列中。
特点:
- 明确路由键,并根据路由键发送消息
- 负载均衡发生在消费者之间
扇形交换机(Fanout exchange)
扇形交换机(Fanout exchange)将消息分发到所有绑定到交换机上的队列,不用关心绑定的路由键,类似于广播。常用案例:
- 大规模多用户在线(MMO)游戏可以使用它来处理排行榜更新等全局事件
- 体育新闻网站可以用它来近乎实时地将比分更新分发给移动客户端
- 分发系统使用它来广播各种状态和配置更新
- 在群聊的时候,它被用来分发消息给参与群聊的用户。(AMQP没有内置presence的概念,因此XMPP可能会是个更好的选择)
特点:
- 不理会绑定的路由键
- 消息分发到所有绑定队列中
主题交换机(Topic exchange)
主题交换机(Topic exchange)通过对发送到交换机的消息的路由将进行匹配,将消息发送到一个或者多个队列当中,主题交换机通常用来实现消息的多播路由。使用案例:
- 分发有关于特定地理位置的数据,例如销售点
- 由多个工作者(workers)完成的后台任务,每个工作者负责处理某些特定的任务
- 股票价格更新(以及其他类型的金融数据更新)
- 涉及到分类或者标签的新闻更新(例如,针对特定的运动项目或者队伍)
- 云端的不同种类服务的协调
- 分布式架构/基于系统的软件封装,其中每个构建者仅能处理一个特定的架构或者系统
特点:
- 通过*和#进行路由键匹配
- 多播路由
头交换机(Headers exchange)
头交换机(headers exchange)使用多个消息属性来代替路由键建立路由规则。通过判断消息头的值能否与指定的绑定相匹配来确立路由规则。头交换机可以视为直连交换机的另一种表现形式。头交换机能够像直连交换机一样工作,不同之处在于头交换机的路由规则是建立在头属性值之上,而不是路由键。路由键必须是一个字符串,而头属性值则没有这个约束,它们甚至可以是整数或者哈希值(字典)等。
1.5 相关参考
2.RabbitMQ搭建
2.1 单点搭建
官方给出的RabbitMQ和Erlang对应版本
| RabbitMQ版本 | Erlang最低版本 | Erlang最高版本 |
|---|---|---|
| 3.7.15 | 20.3.x | 22.0.x |
| 3.7.14、3.7.13、3.7.12、3.7.11 3.7.10、3.7.9、3.7.8、3.7.7 | 20.3.x | 21.3.x |
| 3.7.6、3.7.5、3.7.4、3.7.3 3.7.2、3.7.1、3.7.0 | 19.3 | 20.3.x |
选用版本:
- Erlang:21.0(otp_src_21.0.tar.gz)
- RabbitMQ:3.1.16(rabbitmq-server-3.7.16-1.el7.noarch.rpm)
Step 1. 安装各种依赖模块
yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel
在configure后会出下如下报错
*********************************************************************
********************** APPLICATIONS DISABLED **********************
*********************************************************************
odbc : ODBC library - link check failed
*********************************************************************
*********************************************************************
********************** APPLICATIONS INFORMATION *******************
*********************************************************************
wx : wxWidgets not found, wx will NOT be usable
安装unixODBC和unixODBC-devel即可,至于第二错报错wxWidgets可以不安装
yum install unixODBC unixODBC-devel
至此安装环境准备完毕
Step 2. Erlang安装
1.解压安装包
tar -xvf otp_src_21.0.tar.gz
安装包没有用gzip格式压缩,所以不加z参数,如果使用tar -zxvf解压则会报错
tar -zxvf otp_src_21.0.tar.gz
gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now
2.进入文件夹(otp_src_21.0)
./configure --prefix=/usr/local/erlang
make && make install
--prefix后为自定义安装路径 3.配置环境变量 在/etc/profile文件中追加
export ERLANG_HOME=/usr/local/erlang
export PATH=$JAVA_HOME/bin:$PATH:$ERLANG_HOME/bin
执行命令 source /etc/profile 加载配置文件 4.验证 输入erl进入控制台
[root@localhost bin]# erl
Erlang/OTP 21 [erts-10.0] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [hipe]
Eshell V10.0 (abort with ^G)
1>
Erlang安装完成
Step 3. RabbitMQ安装
执行命令
rpm -ivh --nodeps rabbitmq-server-3.7.16-1.el7.noarch.rpm
启动rabbitmq服务(rabbitmq-server restart):
[root@localhost /]# rabbitmq-server restart
## ##
## ## RabbitMQ 3.7.16. Copyright (C) 2007-2019 Pivotal Software, Inc.
########## Licensed under the MPL. See https://www.rabbitmq.com/
###### ##
########## Logs: /var/log/rabbitmq/rabbit@localhost.log
/var/log/rabbitmq/rabbit@localhost_upgrade.log
Starting broker...
completed with 0 plugins.
RabbitMQ已安装完成,启动管理插件
[root@localhost /]# rabbitmq-plugins enable rabbitmq_management
Enabling plugins on node rabbit@localhost:
rabbitmq_management
The following plugins have been configured:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
Applying plugin configuration to rabbit@localhost...
The following plugins have been enabled:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
再重启RabbitMQ服务,访问http://192.168.108.128:15672/ 进入管理页面
2.2 安装中遇到的问题
问题1: erlang >= 20.3 被 rabbitmq-server-3.7.16-1.el7.noarch 需要
错误:依赖检测失败:
erlang >= 20.3 被 rabbitmq-server-3.7.16-1.el7.noarch 需要
socat 被 rabbitmq-server-3.7.16-1.el7.noarch 需要
解决: 添加参数--nodeps
rpm -ivh --nodeps rabbitmq-server-3.7.16-1.el7.noarch.rpm
问题2: socat 被 rabbitmq-server-3.7.16-1.el7.noarch 需要 安装依赖socat
wget http://ftp.tu-chemnitz.de/pub/linux/dag/redhat/el6/en/x86_64/rpmforge/RPMS/socat-1.7.2.4-1.el6.rf.x86_64.rpm
问题3: 安装socat时tcp_wrappers 被 socat-1.7.2.4-1.el6.rf.x86_64 需要
错误:依赖检测失败:
tcp_wrappers 被 socat-1.7.2.4-1.el6.rf.x86_64 需要
解决: 安装tcp_wrappers
yum -y install tcp_wrappers
2.3 集群搭建
一般集群
集群服务器三台
| 服务器名 | ip |
|---|---|
| node1 | 192.168.108.128 |
| node2 | 192.168.108.129 |
| node3 | 192.168.108.130 |
1.进入/var/lib/rabbitmq文件夹中,查看.erlang.cookie内容,保证三台服务器的.erlang.cookie文件内容一致 2.启动三台服务器的RabbitMQ服务 3.在node2、node3上关闭RabbitMQ应用
[root@node2 ~]# rabbitmqctl stop_app
[root@node3 ~]# rabbitmqctl stop_app
4.将服务器node2、node3加入到服务器节点node1中
[root@node2 ~]# rabbitmqctl join_cluster --ram rabbit@node1
[root@node3 ~]# rabbitmqctl join_cluster --ram rabbit@node1
5.开启无服务的RabbitMQ应用
[root@node2 ~]# rabbitmqctl start_app
[root@node3 ~]# rabbitmqctl start_app
6.在node1管理界面查看节点情况
集群配置成功
HA集群
RabbitMQ集群搭建参考官方文档: RabbitMQ HA集群搭建
2.4 参考
SpringBoot整合RabbitMQ——Direct交换机
SpringBoot整合RabbitMQ——Fanout交换机