优秀的编程知识分享平台

网站首页 > 技术文章 正文

RabbitMQ入门-消息订阅模式(rss订阅)

nanyue 2024-08-08 18:49:32 技术文章 14 ℃

消息派发

上篇《RabbitMQ入门-消息派发那些事儿》发布之后,收了不少反馈,其中问的最多的还是有关消息确认以及超时等场景的处理。

楼主,有遇到消费者后台进程不在,但consumer连接还在,当前消息是unacked状态,导致这个消息一直不被消费

队列在等待回复的时候,这个消息是怎么存放的?如果一直没有返回有超时么?

...

这里再对消息确认做以下补充

有关超时

RabbitMQ是没有超时概念的,如果一个消费者消费一条消息要花费很长时间,比如10分钟,那么这个过程会一直进行下去。除非你采用其他策略来中断它或者重试。

消费者挂了怎么办

如果我们不打开自动确认的标识autoAck,那么消费者在消费完成消息之后会发送一个确认标识给RabbitMQ。RabbitMQ接收到这个标识之后,就会将这条消息从内存中删除。

但是正如上面的网友提到的那样,如果消费者后台进程不在即消费者挂了,这时候RabbiMQ会一直傻等着么?当然不会,RabbitMQ发现消费者挂了之后,它会很快将这条消息转而批发给下一个消费者消费,这样做也能够避免消息丢失的情况。

下面我们启动了两个消费者,一个发送端,在第二个消费者接收到消息的时候,手动让其进程结束,这时候我们会发现最终生产的4条消息都被第一个消费者消费了,并没有出现消息丢失的情况。

消息持久化

上面的情况是在RabbitMQ正常提供服务时避免了消息丢失的情况,但是如果遇到RabbitMQ服务挂了,该如何保证消息不丢失呢?这时候就需要做持久化,细心的同学应该已经发现,在Work模式的发送端和接收端都做了持久化。

channel.basicPublish("", TASK_QUEUE_NAME,MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes("UTF-8"));

这里第三个参数指明了要持久化

channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);

这里第二个参数知名了要持久化

订阅者模式

模型组成

一个消费者Producer,一个交换机Exchange,多个消息队列Queue,多个消费者Consumer

Exchange

相比较于前两种模型Hello World和Work,这里多一个一个Exchange。其实Exchange是RabbitMQ的标配组成部件之一,前两种没有提到Exchange是为了简化模型,即使模型中没有看到Exchange的声明,其实还是声明了一个默认的Exchange。

RabbitMQ中实际发送消息并不是直接将消息发送给消息队列,消息队列也没那么聪明知道这条消息从哪来要到哪去。RabbitMQ会先将消息发送个Exchange,Exchange会根据这条消息打上的标记知道该条消息从哪来到哪去。

Exchange凭什么知道消息的何去何从,因为Exchange有几种类型:direct,fanout,topic和headers。这里说的订阅者模式就可以认为是fanout模式了。

订阅者模式有何不同

订阅者模式相对前面的Work模式有和不同?Work也有多个消费者,但是只有一个消息队列,并且一个消息只会被某一个消费者消费。但是订阅者模式不一样,它有多个消息队列,也有多个消费者,而且一条消息可以被多个消费者消费,类似广播模式。下面通过实例代码看看这种模式是如何收发消息的。

发送端

  • channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);添加了Exchange的声明,并且采用的是fanout类型

  • channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));声明了Exchange的名称,而不是像之前那样给了个空值

接收端

  • 这里通过String queueName = channel.queueDeclare().getQueue();来声明队列,采取该种方式会生成一个随机名字的消息队列,并且在断开连接时队列会自动删除,但是这并不会影响订阅者模式,因为该场景下所有绑定的queue都会收到消息

  • 通过channel.queueBind(queueName, EXCHANGE_NAME, "");将新建的Queue和Exchange绑定,因为是fanout模式,所以不需要指定routing key的值

  • 启动了两个随机名称的消费者,它们Queue的名称不同

  • 启动生产者,发送一条消息,这时候可以发现两个接受端都收到了消息,这就是订阅者模式

最近发表
标签列表