天天看点

RabbitMQ设计理解-使用模式(场景)

简介:

基于队列消费的模式,Rabbit提供了集中使用的场景模式。

1 直推模式

直推模式中消息只做简单的发送和接

RabbitMQ设计理解-使用模式(场景)

2 多工作者模式

多工作者模式中,推送任务消息之后,由于有的任务是耗时的任务,当耗时任务的时候,很长时间才会返回确认消息或者是断开了连接等情况很容易导致队列的阻塞。如果处理端能有多个,那么可以极大的提高效率和容错。

RabbitMQ设计理解-使用模式(场景)

3 发布订阅模式(Exchange)

发布订阅模式中,消息的发布者与消息的接受者不再直接操作于队列,而是通过将exchange与队列关联起来。消息的发送与接收都与exchange关联起来,不再受队列的约束。在发布订阅模式中,队列不再限制,一个客户端可以将任意队列与exchange绑定(某种程度上也可以避免死队列)。

在订阅模式中广播的方式有三种:

1 全局广播(exchange=finout)

对于所有订阅了的终端全局都发送发布的消息,全局的消息。

RabbitMQ设计理解-使用模式(场景)

2 局域广播(exchange=direct)

在全局广播的基础上,有些广播希望只被部分订阅方看到,此时有个routing_key实现该功能。routing_key起到的作用其实可以看做是分组,将声明了相同routing_key的客户端分配在一个组,并且接收"routing_key"组的消息。

RabbitMQ设计理解-使用模式(场景)

3 混合广播(exchange=topics)

混合广播的方式是将上面两种方式的优点结合起来,既支持全局广播,也支持局域广播,在声明exchange的时候需要声明"topics",并且使用适配符(通配符+ '.'):

  • * (star) can substitute for exactly one word.(*字符代表一个字符)
  •  # (hash) can substitute for zero or more words.(#代表0或者多个字符)

例如:*.orange.* , lazy.#

来实现客户端既可以接收全局的广播也可以接收

RabbitMQ设计理解-使用模式(场景)

二、Rabbit 中需要注意的一些机制

1 确认机制

队列的确认机制我觉得很有必要讲清楚,确认机制应该是和我们的实际使用场景息息相关,下面就我对官网阅读之后的一些理解:

RabbitMQ在默认的情况下,是会自动实现:发布方发送消息给队列,队列分发给客户端,客户端在接受到消息,并且处理完之后发送一个ACK(确认)。

       在正常情况下,是比较好的机制。但是当我们希望任务不能被丢失,也就是说任务一定会被执行,在特殊情况下可能不能满足(队列连接断开,TCP断开连接,http层断开连接等)。当特殊情况发生的时候,Worker1队列断开连接,我们没有办法确认是在什么环节出现的问题。这个时候如果尝试关闭自动确认机制,那么只要没有收到消息的确认ACK,队列就会给另外正常的队列Worker2(如果没有正常的队列会在下次绑定该队列的时候下发消息)发送消息并让Worker2去完成任务。这样就达到了任务消息不会丢失。

RabbitMQ设计理解-使用模式(场景)

当关闭了自动确认机制之后,队列就会保存任务消息,每当有客户端连接到队列或者已经有绑定队列的Worker,就会下发任务消息到该Worker,直到某个队列通过tag(Long)回复一个ack为止。这种机制能很大程度的保证消息不会丢失

2 队列存储(持久性)

基于确认机制保证了消息不会丢失,但是当服务端挂掉或者意外停机时,所有队列都会队列中的消息也会丢失,所以为了解决这种情况RabbitMQ提供了持久化队列的方式:

RabbitMQ设计理解-使用模式(场景)

队列声明持久化(发送方和接收方都需要持久化声明)之后,发送的消息也需要声明持久化

RabbitMQ设计理解-使用模式(场景)

持久化需要注意的点:

上面的持久化并不是意味着完全精准的实现了消息不会丢失。尽管RabbitMQ会保存消息到硬盘,但是在接收到消息到保存到硬盘之间还是有一个很短的时间窗。RabbitMQ不会为每一个消息做fsync,可能是先保存在缓存,然后再保存在硬盘上。所以RabbitMQ的持久化并不是很完善,但是相比简单的任务队列来说已经足够了。如果希望一个更加完善的持久化方案参考:(https://www.rabbitmq.com/confirms.html)

RabbitMQ设计理解-使用模式(场景)

3 单队列多Worker对等机制

       在上面说到的多工作者模式当中,我们应该注意的是,默认情况下RabbitMQ会平均的为每一个Worker分配对等的任务,也就是说队列消费是平均的,不会出现某个Worker一直空闲,某个Worker一直繁忙的情况。但是,针对于一些比较特殊的任务来说,比如耗时的任务,这个时候如果还是平均分配的话就会出现某个Worker任务阻塞,因为耗时任务还未完成就又推送新的任务的情况。这个时候RabbitMQ提供的解决方案是(QOS):

RabbitMQ设计理解-使用模式(场景)