RabbitMQ入门教程

摘要: 使用RabbitMQ的消息队列,可以有效提高系统的峰值处理能力。

RabbitMQ是消息代理(Message Broker),它支持多种异步消息处理方式,最常见的有:

Work Queue:将消息缓存到一个队列,默认情况下,多个worker按照Round Robin的方式处理队列中的消息。每个消息只会分配给单个worker。

Publish/Subscribe:每个订阅消息的消费者都会收到消息,因此每个消息通常会分配给多个worker,每个worker对消息进行不同的处理。

RabbitMQ还支持Routing、Topics、以及Remote procedure calls (RPC)等方式。

对于不同的消息处理方式,有一点是相同的,RabbitMQ是介于消息的生产者和消费者的中间节点,负责缓存和分发消息。RabbitMQ接收来自生产者的消息,缓存到内存中,按照不同的方式分发给消费者。RabbitMQ还可以将消息写入磁盘,保证持久化,这样即使RabbitMQ意外崩溃了,消息数据不至于完全丢失。

为什么使用RabbitMQ?

最简单的一点在于,它支持Work Queue等不同的消息处理方式,可以用于不同的业务场景。RabbitMQ的Work Queue,即消息队列。

使用消息队列,可以将不算紧急、但是非常消耗资源的计算任务,以消息的方式插入到RabbitMQ的队列中,然后使用多个处理模块处理这些消息。

这样做最大的好处在于:提高了系统峰值处理能力。因为,来不及处理的消息缓存在RabbitMQ中,避免了同时进行大量计算导致系统因超负荷运行而崩溃。而那些来不及处理的消息,会在峰值过去之后慢慢处理掉。

另一个好处在于解耦。消息的生产者只需要将消息发送给RabbitMQ,这些消息什么时候处理完,不会影响生产者的响应性能。

安装并运行RabbitMQ

使用Docker运行RabbitMQ非常简单,只需要执行一条简单的命令:

sudo docker run -d --name rabbitmq -h rabbitmq -p 5672:5672 -v /var/lib/rabbitmq:/var/lib/rabbitmq registry.docker-cn.com/library/rabbitmq:3.7

-d : 后台运行容器

–name rabbitmq : 将容器的名字设为rabbitmq

-h rabbitmq : 将容器的主机名设为rabbitmq,希望RabbitMQ消息数据持久化保存到本地磁盘是需要设置主机名,因为RabbitMQ保存数据的目录为主机名

-p 5672:5672 : 将容器的5672端口映射为本地主机的5672端口,这样可以通过本地的5672端口访问rabbitmq

-v /var/lib/rabbitmq:/var/lib/rabbitmq:将容器的/var/lib/rabbitmq目录映射为本地主机的/var/lib/rabbitmq目录,这样可以将RabbitMQ消息数据持久化保存到本地磁盘,即使RabbitMQ容器被删除,数据依然还在。

消费者的消息确认机制

rabbitmq怎么知道消息被接受了呢?

acknowledge 确认机制  用手动模式

work消息模型(任务模型)

队列里的消息越来越多,内存总有存满的一天消息会丢失,消息堆积。耗时较长的比如发短信,需要用mq。

让多个消费者绑定一个队列,共同消费队列中的消息。队列中的消息一旦消费,就会消失,因此任务是不会被重复执行的。

channel.basicQos(1); 设置每次消费一个信息,解决消息堆积问题。


2.3.订阅模型分类

1、1个生产者,多个消费者

2、每一个消费者都有自己的一个队列

3、生产者没有将消息直接发送到队列,而是发送到了交换机

4、每个队列都要绑定到交换机

5、生产者发送的消息,经过交换机到达队列,实现一个消息被多个消费者获取的目的


X(Exchanges):交换机一方面:接收生产者发送的消息。另一方面:知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。

Exchange类型有以下几种:

        Fanout:广播,将消息交给所有绑定到交换机的队列

        Direct:定向,把消息交给符合指定routing key 的队列

        Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列

我们这里先学习

Fanout:即广播模式

Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!


订阅模型-Fanout

1) 可以有多个消费者

2)  每个消费者有自己的queue(队列)

3)  每个队列都要绑定到Exchange(交换机)

4)  生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。

5)  交换机把消息发送给绑定过的所有队列

6)  队列的消费者都能拿到消息。实现一条消息被多个消费者消费

两个变化:

1)  声明Exchange,不再声明Queue

2)  发送消息到Exchange,不再发送到Queue

步骤:

// 获取到连接

// 获取通道

// 声明队列

// 绑定队列到交换机

// 定义队列的消费者

// 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用

// 监听队列,手动返回完成

订阅模型-Direct

有选择性的接收消息

在订阅模式中,生产者发布消息,所有消费者都可以获取所有消息。

在路由模式中,我们将添加一个功能 - 我们将只能订阅一部分消息。 例如,我们只能将重要的错误消息引导到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。

但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。

在Direct模型下,队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)

消息的发送方在向Exchange发送消息时,也必须指定消息的routing key

绑定队列到交换机,同时指定需要订阅的routing key。需要 update、delete


订阅模型-Topic

Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符!

Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert

通配符规则:

        #:匹配一个或多个词

        *:匹配不多不少恰好1个词

举例:

        audit.#:能够匹配audit.irs.corporate 或者 audit.irs

        audit.*:只能匹配audit.irs

面试题:

如何避免消息丢失?

1)  消费者的ACK机制。可以防止消费者丢失消息。

2)  但是,如果在消费者消费之前,MQ就宕机了,消息就没了。

是可以将消息进行持久化呢?

要将消息持久化,前提是:队列、Exchange都持久化

durable 持久化

AmqpTemplate 统一的spring消息处理模板;

你可能感兴趣的:(RabbitMQ入门教程)