上一篇 RabbitMQ 入门 对 RabbitMQ 作了入门了解并介绍了他的一种工做模式-简单模式。本篇来学习一下 RabbitMQ 的第二种工做模式 - work queue。学习
先来看官网的一张图, 如图所示,咱们能够看到,与上一篇介绍的简单模式不一样之处在于,这里存在多个消费者。多个消费者如何处理队列中的消息,咱们后面会说道。fetch
work queue 的思想 是避免当即去执行一些耗时任务,而且一直等待任务完成, 而是分发耗时的任务给多个worker, 也就是生产者将消息发送到队列,而后消费者能够轮流从队列中读取消息。spa
接下来介绍 RabbitMQ 使用过程当中容易遇到的问题,以及解决办法。.net
消息确认机制做用是当某个客户端忽然挂掉了,消息不会丢失。code
处理一个消息须要几秒钟,你可能想知道,当一个消费者正在处理一个很耗时的任务时,挂掉了会发生什么。若是不作特殊处理,当mq把消息传递给消费者时, 这个消息就会被当即删除。因此此时若是你杀掉一个消费者时,这个消费者正在处理以及未处理的消息都会丢失。面对以上的状况,咱们一般想把消息交给其余消费者去处理。这个时候咱们就可使用rabbitmq的消息确认机制-消费者收到消息后,会去通知mq我已经收到消息了,而后你能够把消息删除了。若是一个消费者挂掉了,而且没有发送 ack 给生产者,此时生产者就会当即把消息从新发送到另外一个还活着的消费者手中。消息确认机制默认是打开的,(autoAck=false)channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); 若是忘记 basicAck,会带来很严重的后果,若是你的客户端退出,消息会从新发送,最终RabbitMQ 会吃掉不少内存。
blog
消息持久化的做用是当RabbitMQ Server 挂掉了,消息不会丢失rabbitmq
当mq 退出或崩掉的时候,它就会“忘记”那些队列和消息,除非你告诉他。解决这种问题的办法就是将队列 和 消息本地持久化。
队列
在消费者和生产者客户端同时声明 channel.queueDeclare("hello", durable, false, false, null);// durable = true; 这里须要注意的是: RabbitMQ 是不容许建立一个已存在的队列的,即便你使用不一样参数。
channel.basicPublish("", "task_queue", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
注意: 即便作了消息持久化,也不能彻底保证消息丢失,在RabbitMQ 接收到消息还没保存的这段时间,消息仍有可能会丢失。所以消息持久化仅仅能知足一些简单的任务队列。若是须要更加健壮的机制,须要学习下 Publisher Confirms
内存
若是咱们有奇数个 "重量级" 的消息,和偶数个 "轻量级" 的消息, 那么在咱们的程序运行中,会出现一个 worker 老是很忙的状况, 由于它不停地在处理 那些 "重量级" 的消息。可是RabbitMQ 殊不知道谁轻松谁不轻松。get
`channel.basicQos(prefetchCount);// prefetchCount = 1;`
这行代码的做用就是告诉 RabbitMQ 不要在某一时刻,发送多个消息给worker, 等worker 确认完以后,再发送