消息总线 (Message Queue),是一种跨进程、异步的通信机制,用于上下游传递消息。由消息系统来确保消息的可靠传递。
当前市面上 mq 的产品很多,比如 RabbitMQ、Kafka、ActiveMQ、ZeroMQ 和阿里巴巴捐献给 Apache 的 RocketMQ。甚至连 redis 这种 NoSQL 都支持 MQ 的功能。
- 上下游逻辑解耦 && 物理解耦
- 保证数据最终一致性
- 广播
- 错峰流控等等
RabbitMQ 是由 Erlang 语言开发的 AMQP 的开源实现。
AMQP:Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言灯条件的限制。
可靠性(Reliablity):
使用了一些机制来保证可靠性,比如持久化、传输确认、发布确认。灵活的路由(Flexible Routing):
在消息进入队列之前,通过 Exchange 来路由消息。对于典型的路由功能,Rabbit 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange。消息集群(Clustering):
多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker。高可用(Highly Avaliable Queues)
:队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。多种协议(Multi-protocol):
支持多种消息队列协议,如 STOMP、MQTT 等。多种语言客户端(Many Clients):
几乎支持所有常用语言,比如 Java、.NET、Ruby 等。管理界面(Management UI)
:提供了易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。跟踪机制(Tracing)
:如果消息异常,RabbitMQ 提供了消息的跟踪机制,使用者可以找出发生了什么。插件机制(Plugin System)
:提供了许多插件,来从多方面进行扩展,也可以编辑自己的插件。
所有 MQ 产品从模型抽象来说,都是一样的过程:
- 消费者 (consumer) 订阅某个队列。
- 生产者 (product) 创建消息,然后发布到队列中(queue),最终将消息发送到监听的消费者。
这只是最简单抽象的描述,具体到 RabbitMQ 则由更详细的概念需要解释。
Broker:
标识消息队列服务器实体.Virtual Host:
虚拟主机。标识一批交换机、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在链接时指定,RabbitMQ 默认的 vhost 是 /。Exchange:
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。Queue:
消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。Banding:
绑定,用于消息队列和交换机之间的关联。一个绑定就是基于路由键将交换机和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。Channel:
信道,多路复用连接中的一条独立的双向数据流通道。新到是建立在真实的 TCP 连接内地虚拟链接,AMQP 命令都是通过新到发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说,建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。Connection:
网络连接,比如一个 TCP 连接。Publisher:
消息的生产者,也是一个向交换器发布消息的客户端应用程序。Consumer:
消息的消费者,表示一个从一个消息队列中取得消息的客户端应用程序。Message:
消息,消息是不具名的,它是由消息头和消息体组成。消息体是不透明的,而消息头则是由一系列的可选属性组成,这些属性包括 routing-key(路由键)、priority(优先级)、delivery-mode(消息可能需要持久性存储 [消息的路由模式]) 等。
- 消息产生着 § 将消息放入队列
- 消息的消费者 (consumer) 监听(while) 消息队列, 如果队列中有消息, 就消费掉, 消息被拿走后, 自动从队列中删除(隐患 消息可能没有被消费者正确处理, 已经从队列中消失了, 造成消息的丢失) 应用场景: 聊天(中间有一个过度的服务器; p 端, c 端)
- 消息产生者将消息放入队列消费者可以有多个, 消费者 1, 消费者 2, 同时监听同一个队列, 消息被消费? C1 C2 共同争抢当前的消息队列内容, 谁先拿到谁负责消费消息 (隐患, 高并发情况下, 默认会产生某一个消息被多个消费者共同使用, 可以设置一个开关 (syncronize, 与同步锁的性能不一样) 保证一条消息只能被一个消费者使用)
- 应用场景: 红包; 大项目中的资源调度 (任务分配系统不需知道哪一个任务执行系统在空闲, 直接将任务扔到消息队列中, 空闲的系统自动争抢)
- X 代表交换机 rabbitMQ 内部组件, erlang 消息产生者是代码完成, 代码的执行效率不高, 消息产生者将消息放入交换机, 交换机发布订阅把消息发送到所有消息队列中, 对应消息队列的消费者拿到消息进行消费
- 相关场景: 邮件群发, 群聊天, 广播 (广告)
- 消息生产者将消息发送给交换机按照路由判断, 路由是字符串 (info) 当前产生的消息携带路由字符 (对象的方法), 交换机根据路由的 key, 只能匹配上路由 key 对应的消息队列, 对应的消费者才能消费消息;
- 根据业务功能定义路由字符串
- 从系统的代码逻辑中获取对应的功能字符串, 将消息任务扔到对应的队列中业务场景: error 通知; EXCEPTION; 错误通知的功能; 传统意义的错误通知; 客户通知; 利用 key 路由, 可以将程序中的错误封装成消息传入到消息队列中, 开发者可以自定义消费者, 实时接收错误;
- 星号井号代表通配符
- 星号代表多个单词, 井号代表一个单词
- 路由功能添加模糊匹配
- 消息产生者产生消息, 把消息交给交换机
- 交换机根据 key 的规则模糊匹配到对应的队列, 由队列的监听消费者接收消息消费
-
✴️版权声明 © :本书所有内容遵循CC-BY-SA 3.0协议(署名-相同方式共享)©