RabbitMq五种模式
1)Simple-简单模型
RabbitMQ是一个消息代理:它接受和转发消息。 你可以把它想象成一个邮政信箱
RabbitMQ与邮局的主要区别是它不处理纸张,而是接受,存储和转发数据消息的二进制数据块。
P(producer/ publisher):生产者,一个发送消息的用户应用程序。
C(consumer):消费者,消费和接收有类似的意思,消费者是一个主要用来等待接收消息的用户应用程序
队列(红色区域):rabbitmq内部类似于邮箱的一个概念。虽然消息流经rabbitmq和你的应用程序,但是它们只能存储在队列中。队列只受主机的内存和磁盘限制,实质上是一个大的消息缓冲区。许多生产者可以发送消息到一个队列,许多消费者可以尝试从一个队列接收数据。
2)消息确认机制(ACK)非模型
RabbitMQ有一个ACK机制。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。
不过这种回执ACK分两种情况:
(1)自动ACK:消息一旦被接收,消费者自动发送ACK
(2)手动ACK:消息接收后,不会发送ACK,需要手动调用
需要用到哪种,根据消息的重要性来看:
如果消息不太重要,丢失也没关系的话就用自动ACK
如果消息非常重要,不容丢失,使用手动ACK
注重消息丢失,使用自动ACK
注重业务逻辑失败回滚消息,使用手动ACK
如果第二个参数为true,则会自动进行ACK;如果为false,则需要手动ACK。
channel.basicConsume(QUEUE_NAME, false, consumer);
自动ACK存在的问题 ---- 出现异常后消息人会被消费
修改消费者,添加异常,如下:
image.png
生产者不做任何修改,直接运行,消息发送成功:
image.png
运行消费者,程序抛出异常。但是消息依然被消费:
image.png
演示手动ACK
修改消费者,把自动改成手动(去掉之前制造的异常)
image.png
运行消费者
image.png
停掉消费者的程序,发现:
image.png
这是因为虽然我们设置了手动ACK,但是代码中并没有进行消息确认!所以消息并未被真正消费掉。
当我们关掉这个消费者,消息的状态再次称为Ready
修改代码手动ACK:
image.png
Work-工作模型
image.png创建一个工作队列,在多个工作者之间分配耗时任务---平均分发
工作队列,又称任务队列。主要思想就是避免执行资源密集型任务时,必须等待它执行完成。相反我们稍后完成任务,我们将任务封装为消息并将其发送到队列。 在后台运行的工作进程将获取任务并最终执行作业。当你运行许多消费者时,任务将在他们之间共享,但是一个消息只能被一个消费者获取。
接下来我们来模拟这个流程:
P:生产者:任务的发布者
C1:消费者,领取任务并且完成任务,假设完成速度较快
C2:消费者2:领取任务并完成任务,假设完成速度慢
避免消息堆积?
采用workqueue,多个消费者监听同一队列。
接收到消息以后,而是通过线程池,异步消费。
Fanout-广播模型
image.png在广播模式下,消息发送流程是这样的:
可以有多个消费者
每个消费者有自己的queue(队列)
每个队列都要绑定到Exchange(交换机)
生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
交换机把消息发送给绑定过的所有队列
队列的消费者都能拿到消息。实现一条消息被多个消费者消费
Direct-定向模型
选择性的接收消息
队列上的全部消息绑定在一个交换机上,通过路由key,路由分配到对应的消费者上
使用场景:电商系统有“南区”,“北区”,“华南区”仓库,下单的时候将发货请求发到发货队列上,通过路由key,分发到对应仓库进行消费发货。
1.在订阅模式中,生产者发布消息,所有消费者都可以获取所有消息。
在路由模式中,我们将添加一个功能 - 我们将只能订阅一部分消息。 例如,我们只能将重要的错误消息引导到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。
2.但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。
在Direct模型下,队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
消息的发送方在向Exchange发送消息时,也必须指定消息的routing key
P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing key完全匹配的队列
C1:消费者,其所在队列指定了需要routing key 为 error 的消息
C2:消费者,其所在队列指定了需要routing key 为 info、error、warning 的消息
Topic-主题模型
Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。
只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符!
Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert
通配符规则:
image.png
#
:匹配一个或多个词
*
:匹配不多不少恰好1个词
audit.#
:能够匹配audit.irs.corporate
或者audit.irs
audit.*
:只能匹配audit.irs
在这个例子中,我们将发送所有描述动物的消息。消息将使用由三个字(两个点)组成的routing key发送。路由关键字中的第一个单词将描述速度,第二个颜色和第三个种类:“<speed>.<color>.<species>”。
我们创建了三个绑定:Q1绑定了绑定键“.orange.”,Q2绑定了“..rabbit”和“lazy.#”。
Q1匹配所有的橙色动物。
Q2匹配关于兔子以及懒惰动物的消息。