RabbitMQ-概念篇

167 阅读6分钟

MQ的优势

  • 应用解耦

    当不同模块之间的依赖关系复杂时,使用 RabbitMQ 可以解耦模块,使它们通过消息进行通信,互不影响。

  • 异步提速

    对于一些非关键路径的操作,如发送邮件、生成报表等,可以通过 RabbitMQ 异步处理,提高系统的响应速度。

  • 削峰填谷

    在高并发场景下,通过 RabbitMQ 缓存请求,避免后端服务瞬间被大量请求压垮。

MQ的劣势

  • 系统可用性降低

    系统引入的外部依赖越多,系统稳定性越差。一旦 MQ 宕机,就会对业务造成影响。如何保证MQ的高可用?

  • 系统复杂度提高

    MQ 的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过 MQ 进行异步调用。如何保证消息不被丢失等情况?

术语

  • Virtual host(虚拟主机)

    出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,类似于网络中的namespace概念。当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue 等。

  • Exchange(交换机)

    交换机是RabbitMQ中实现消息路由的核心组件。生产者将消息发送到交换机,交换机根据路由键和绑定规则将消息分发到不同的队列中。RabbitMQ提供了多种类型的交换机,包括直接交换机(Direct)、扇出交换机(Fanout)、主题交换机(Topic)和消息头交换机(Headers)等。

  • Queue(队列)

    队列是RabbitMQ中用于存储和转发消息的容器。生产者将消息发送到队列中,而消费者则从队列中取出并处理这些消息。队列具有先进先出(FIFO)的特性,即先进入队列的消息会先被消费者取出。队列还具有持久化的特性,可以将消息存储在磁盘上,以防止RabbitMQ服务器重启后消息的丢失。此外,队列还可以设置其他属性,如是否独占、是否自动删除等。

  • Connection(连接)

    连接RabbitMQ和应用服务器的TCP连接。

  • Channel(信道)

    连接里的一个虚拟通道,通过消息队列发送或者接收消息时,都是通过信道进行的。

  • Producer(生产者)

    生产者是消息的发送方,它将消息发送到RabbitMQ的交换机中。生产者可以指定消息的路由键和交换机的名称,以控制消息的路由和分发。

  • Consumer(消费者)

    消费者是消息的接收方,它从RabbitMQ的队列中获取并处理消息。消费者可以监听一个或多个队列,当队列中有新消息时,消费者会将其取出并处理。

  • Broker(代理)

    接收和分发消息的应用,RabbitMQ Server就是Message Broker。

交换机

  1. Default Exchange

默认交换机是一个预定义的无名交换机,它会自动将消息发送到与之路由键名称相同的队列中。当生产者没有显式地指定交换机时,消息会被发送到默认交换机中。

  1. Direct Exchange

直连交换机是最简单的交换机类型,它将消息的路由键和绑定键进行精确匹配,当我们的路由键和绑定键一致的时候,将消息发送到与之完全匹配的队列。

direct-exchange.png 3. Fanout Exchange

扇形交换机将消息广播到所有与之绑定的队列。无论消息的路由键是什么,扇形交换机都会将消息发送到所有绑定的队列中。这种类型的交换机常用于实现发布-订阅模式,将消息广播给多个消费者。

fanout-exchange.png 4. Topic Exchange

主题交换机基于模式匹配的方式将消息路由到队列。它使用通配符来进行匹配,支持通配符符号 "" 和 "#"。其中 "" 表示匹配一个单词,"#" 表示匹配一个或多个单词。

topic-exchange.png 5. Headers Exchange

头交换机和扇形交换机一样都不要路由键,首交换机根据消息Headers的属性进行匹配和路由。在消息发送时,可以指定一组键值对作为消息的头部属性,交换机会根据这些属性进行匹配。首部交换机提供了更灵活的匹配方式,但相对复杂度较高,通常使用较少。

headers-exchange.png

使用交换机的好处

  1. 路由控制

    通过交换机,可以根据消息的路由键将消息路由到与之匹配的队列。这样,可以根据消息的属性或标签来定向分发消息,实现精确的消息路由控制。

  2. 消息过滤

    交换机可以根据消息的路由键、消息头部属性等信息对消息进行过滤和筛选,将符合特定条件的消息发送到相应的队列。这样可以实现消息的订阅和过滤机制,灵活地处理不同类型的消息。

  3. 广播和多播

    通过使用扇形交换机(Fanout Exchange),可以将消息广播到所有与之绑定的队列,实现消息的广播和多播机制,方便实现发布-订阅模式。

  4. 解耦和灵活性

    通过将消息发送到交换机而不是直接发送到队列,生产者和消费者之间实现了解耦。生产者只需要将消息发送到指定的交换机,而不需要知道具体的队列。这样,可以灵活地增加、删除或修改队列,而不会对生产者产生影响。

  5. 可扩展性

    使用交换机可以实现消息的分发和负载均衡机制。通过将消息发送到多个队列,可以实现横向扩展和并发处理,提高系统的吞吐量和性能。

如何保证消息的可靠性

  • RabbitMQ端的数据安全 Data Safety on the RabbitMQ Side
  • 集群环境 Clustering and Queue Content Replication
  • 生产端的数据安全 Data Safety on the Publisher Side
  • 确保消息被路由到队列 Ensuring that Messages are Routed

持久化

  • exchange要持久化
  • queue要持久化
  • message要持久化

生产方确认

  • confirm确认模式
    • 消息成功投递到交换机,返回ack
    • 消息未投递到交换机,发回nack
  • return退回模式
    • 消息投递到交换机了,但是没有路由到队列。返回ACK,及路由失败原因

producer_confirm.png

消费方确认

  • 自动确认:acknowledge="none"(默认)
  • 手动确认:acknowledge="manual"
  • 根据异常情况确认:acknowledge="auto"

consumer_confirm.png

FAQ

  1. 既然已经有了Connection,完全可以使用Connection完成Channel的工作,为什么还要引入Channel这样一个虚拟连接的概念呢?

    因为现在的程序都是支持多线程的,如果没有Channel,那么每个线程在访问RabbitMQ的时候都要建立一个Connection这样的TCP连接,对于操作系统来说, 建立和销毁TCP连接是非常大的开销,在系统访问流量高峰时,会严重影响系统的性能。 Channel就是为了解决这种问题,通常情况下,每个线程创建单独的Channel进行通讯,每个Channel都有自己的channel id帮助Broker和客户端识别Channel, 所以Channel之间是完全隔离的。 Connection与Channel之间的关系可以比作光纤电缆,如果把Connection比作一条光纤电缆,那么Channel就相当于是电缆中的一束光纤。