欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

消息中间件RabbitMQ的核心概念和运行机制

程序员文章站 2024-03-16 10:15:01
...

一、概念

RabbitMQ是一套开源的消息队列服务软件 是由LShift提供的一个AMQP(Advanced Message Queuing Protocol高级消息队列协议)的开源实现
由以高性能 健壮以及可伸缩性出名的Erlang写成
具有很高的稳定性和可靠性

1、核心概念:

  • Message(消息)
    消息是不具名的 它由消息头和消息体组成
    消息体是不透明的 而消息头则由一系列的可选属性组成
    这些属性包括routing-key(路由键 指定消息发送的目的地) 和 priority(相对于其他消息的优先权) 和 delivery-mode(该消息是否需要持久性存储)等属性

  • Publisher(发布者)
    消息的生产者 即一个向交换器发布消息的客户端应用程序

  • Exchange(交换器)
    用于接收生产者发送的消息并将这些消息路由给消息服务器中的队列
    Exchange共有4种类型:direct(默认) 和 fanouttopic 和 和headers
    不同类型的Exchange转发消息的策略有所区别
    direct可实现点对点模型 而fanout 和 topic 和 和headers可实现发布订阅模型

  • Queue(消息队列)
    用于保存消息直到发送给消费者
    它是消息的容器 也是消息的终点 一个消息可被投入一个或多个队列
    消息会一直在队列里面 等待消费者连接到这个队列并将其取走

  • Binding(绑定)
    用于消息队列和交换器之间的关联
    一个绑定就是基于路由键的将交换器和消息队列连接起来的路由规则 因此 可以将交换器理解成一个由绑定构成的路由表
    Exchange和Queue的绑定可以是多对多的关系 一个交换器可以绑定多个队列 而一个队列又可以被多个交换器所绑定
    消息不管发送给哪个交换器 只要绑定了该队列 那么消息都能到达

  • Connection(网络连接)
    是为了操作消息队列而建立的连接

  • Channel(信道)
    对于操作系统来说 建立和销毁TCP连接是非常耗费资源的 因此 引入信道的概念以复用一条TCP连接
    信道是多路复用连接中的一条独立的双向数据流通道 是建立在真实的TCP连接内的多个虚拟连接 AMQP命令是通过信道发送的
    不管是发布消息 订阅队列还是接收消息 这些操作都是通过信道来完成

  • Consumer(消费者)
    消息的消费者 表示一个从消息队列中取得消息的客户端应用程序

  • Virtual Host(虚拟主机)
    表示的是一批交换器 消息队列和相关的对象
    在RabbitMQ服务器上划分了多个虚拟主机 虚拟主机是共享相同的身份认证和加密环境的独立服务器域
    每个Virtual Host(虚拟主机)其本质上就是一个mini版的RabbitMQ服务器 各自拥有自己的队列 交换器 绑定和权限机制
    Virtual Host(虚拟主机)是AMQP 概念的基础 必须在连接时指定
    RabbitMQ默认使用的Virtual Host(虚拟主机)是 /
    可自己指定 例如/abc /employ /department 等

  • Broker(消息代理)
    表示的正是消息队列服务器的实体

示意图:

消息中间件RabbitMQ的核心概念和运行机制
(图画的不太好看 将就一下吧)


2、运行机制:

AMQP消息路由:

RabbitMQ使用的消息服务规范是AMQP消息路由
AMQP中消息的路由过程和Java开发者熟悉的JMS存在一些差别
AMQP中增加了Exchange(交换器)和Binding(绑定)的角色
生产者把消息发布到 Exchange 上 消息最终到达队列并被消费者接收 而 Binding决定了交换器的消息应该发送到哪个队列

Exchange交换器的类型:

Exchange分发消息时根据类型的不同分发策略有所区别 目前共有四种类型:directfanouttopicheaders
由于headers匹配的是AMQP消息的header而不是路由键 模式和direct 交换器完全一致 但性能差很多 目前很少使用 因此不多赘述了


Direct模式:

消息中间件RabbitMQ的核心概念和运行机制
消息中的路由键(routing key)若和Binding中的bindingkey一致 交换器就将消息发到对应的队列中
路由键与队列名必须完全匹配 若一个队列绑定到交换机要求路由键为"dog" 则只会转发routing key标记为"dog"的消息,不会转发"dog.a" 也不会转发"dog.b"等标记的信息
它是完全匹配 单播的模式 是点对点的通信模型


Fanout模式:

消息中间件RabbitMQ的核心概念和运行机制
每个发到fanout类型交换器的消息都会分到所有绑定的队列上去
fanout交换器不处理路由键 只是简单的将队列绑定到交换器上 每个发送到交换器的消息都会被转发到与该交换器绑定的所有队列上
这是广播模式 转发消息的速度是最快的 是JMS模式发布订阅模型的实现
很像子网广播 每台子网内的主机都获得了一份复制的消息


Topic模式:

消息中间件RabbitMQ的核心概念和运行机制
topic交换器通过模式来匹配分配消息的路由键属性 将路由键和某个模式进行匹配 此时队列需要绑定到一个模式上
它将路由键和绑定键的字符串切分成单词 这些单词之间用点隔开
且识别通配符:符号#和符号*
#代表匹配0个或多个单词 *代表匹配一个单词
注:是单词级别的匹配


二、测试

首先 安装RabbitMQ的Docker容器

# 拉取带管理界面的镜像
docker pull docker.mirrors.ustc.edu.cn/library/rabbitmq:3-management

注:版本的后面带management的是有管理界面的

# 启动容器并开放5672和15672端口
docker run -d -p 5672:5672 -p 15672:15672 --name myrabbitmq 479479d8e188 

5672是客户端和RabbitMQ通信的端口 15672是管理界面的端口

浏览器访问ip:15672即可进入管理界面 默认账号密码均为guest

管理界面:
消息中间件RabbitMQ的核心概念和运行机制

然后 创建三个交换器(exchange)用于测试

名为exchange.directexchange.fanoutexchange.topic
分别用于direct类型、fanout类型和topic类型的交换器
消息中间件RabbitMQ的核心概念和运行机制
消息中间件RabbitMQ的核心概念和运行机制
添加完毕

再添加四个用于测试的消息队列(queue)

分别是:zjitczjitc.newszjitc.empsciczjitc.news
消息中间件RabbitMQ的核心概念和运行机制

在添加完毕之后 若要能工作 还须与交换器进行绑定(binding)

绑定direct类型的Exchange:
消息中间件RabbitMQ的核心概念和运行机制
消息中间件RabbitMQ的核心概念和运行机制
绑定完毕

然后 绑定fanout类型的Exchange:
消息中间件RabbitMQ的核心概念和运行机制

最后 再来绑定topic类型的Exchange:
消息中间件RabbitMQ的核心概念和运行机制
消息中间件RabbitMQ的核心概念和运行机制
消息中间件RabbitMQ的核心概念和运行机制
绑定完成

接下来就可以发送消息进行测试了

测试direct交换器

发送消息:
消息中间件RabbitMQ的核心概念和运行机制

发送完毕后会有提示:
消息中间件RabbitMQ的核心概念和运行机制

由于direct交换器是完全匹配的 因此只有名字完全对上的那个queue才能接收到消息:消息中间件RabbitMQ的核心概念和运行机制
成功接收到消息:
消息中间件RabbitMQ的核心概念和运行机制


测试fanout交换器

发送消息:
消息中间件RabbitMQ的核心概念和运行机制
发送完毕后会有提示:
消息中间件RabbitMQ的核心概念和运行机制

所有的queue都收到了消息:消息中间件RabbitMQ的核心概念和运行机制
成功接收到消息:
消息中间件RabbitMQ的核心概念和运行机制


测试topic交换器

测试1 ——

发送消息:
消息中间件RabbitMQ的核心概念和运行机制
发送完毕后会有提示:
消息中间件RabbitMQ的核心概念和运行机制
消息中间件RabbitMQ的核心概念和运行机制
因为前后都能匹配上 因此所有的queue都收到了消息:
消息中间件RabbitMQ的核心概念和运行机制

测试2 ——

发送消息:
消息中间件RabbitMQ的核心概念和运行机制
只能匹配上以news作为后缀的queue:
消息中间件RabbitMQ的核心概念和运行机制
以news结尾的queue收到了消息:
消息中间件RabbitMQ的核心概念和运行机制