RabbitMQ - work queue 工作模式

原创
2019/04/09 20:15
阅读数 146

前言

上一篇 RabbitMQ 入门 对 RabbitMQ 做了入门了解并介绍了他的一种工作模式-简单模式。本篇来学习一下 RabbitMQ 的第二种工作模式 - work queue。


worke queue介绍

先来看官网的一张图, 如图所示,我们可以看到,与上一篇介绍的简单模式不同之处在于,这里存在多个消费者。多个消费者如何处理队列中的消息,我们后面会说道。


work queue 的作用

work queue 的思想 是避免立即去执行一些耗时任务,并且一直等待任务完成, 而是分发耗时的任务给多个worker, 也就是生产者将消息发送到队列,然后消费者可以轮流从队列中读取消息。


RabbitMQ 的一些特性

接下来介绍 RabbitMQ 使用过程中容易遇到的问题,以及解决办法。

消息确认机制

消息确认机制作用是当某个客户端突然挂掉了,消息不会丢失。

处理一个消息需要几秒钟,你可能想知道,当一个消费者正在处理一个很耗时的任务时,挂掉了会发生什么。如果不做特殊处理,当mq把消息传递给消费者时, 这个消息就会被立即删除。所以此时如果你杀掉一个消费者时,这个消费者正在处理以及未处理的消息都会丢失。面对以上的情况,我们通常想把消息交给其他消费者去处理。这个时候我们就可以使用rabbitmq的消息确认机制-消费者收到消息后,会去通知mq我已经收到消息了,然后你可以把消息删除了。如果一个消费者挂掉了,并且没有发送 ack 给生产者,此时生产者就会立即把消息重新发送到另一个还活着的消费者手中。消息确认机制默认是打开的,(autoAck=false)channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); 如果忘记 basicAck,会带来很严重的后果,如果你的客户端退出,消息会重新发送,最终RabbitMQ 会吃掉很多内存。

消息持久化

消息持久化的作用是当RabbitMQ Server 挂掉了,消息不会丢失

当mq 退出或崩掉的时候,它就会“忘记”那些队列和消息,除非你告诉他。解决这种问题的办法就是将队列 和 消息本地持久化。

1. 队列持久化

在消费者和生产者客户端同时声明
channel.queueDeclare("hello", durable, false, false, null);// durable = true;
这里需要注意的是: RabbitMQ 是不允许创建一个已存在的队列的,即使你使用不同参数。

2. 消息持久化

channel.basicPublish("", "task_queue", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());

注意: 即使做了消息持久化,也不能完全保证消息丢失,在RabbitMQ 接收到消息还没保存的这段时间,消息仍有可能会丢失。因此消息持久化仅仅能满足一些简单的任务队列。如果需要更加健壮的机制,需要学习下 Publisher Confirms

Fair dispatch

如果我们有奇数个 "重量级" 的消息,和偶数个 "轻量级" 的消息, 那么在我们的程序运行中,会出现一个 worker 总是很忙的情况, 因为它不停地在处理 那些 "重量级" 的消息。但是RabbitMQ 却不知道谁轻松谁不轻松。

如何预防?

`channel.basicQos(prefetchCount);// prefetchCount = 1;`

这行代码的作用就是告诉 RabbitMQ 不要在某一时刻,发送多个消息给worker, 等worker 确认完之后,再发送

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部