开发者社区> 龙轩8023> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

轻松搞定RabbitMQ(三)——消息应答与消息持久化

简介:        这个官网的第二个例子中的消息应答和消息持久化部分。我把它摘出来作为单独的一块儿来分享。 Message acknowledgment(消息应答)        执行一个任务可能需要花费几秒钟,你可能会担心如果一个消费者在执行任务过程中挂掉了。
+关注继续查看

       这个官网的第二个例子中的消息应答和消息持久化部分。我把它摘出来作为单独的一块儿来分享。


Message acknowledgment(消息应答)

       执行一个任务可能需要花费几秒钟,你可能会担心如果一个消费者在执行任务过程中挂掉了。基于现在的代码,一旦RabbitMQ将消息分发给了消费者,就会从内存中删除。在这种情况下,如果杀死正在执行任务的消费者,会丢失正在处理的消息,也会丢失已经分发给这个消费者但尚未处理的消息。

       但是,我们不想丢失任何任务,如果有一个消费者挂掉了,那么我们应该将分发给它的任务交付给另一个消费者去处理。

       为了确保消息不会丢失,RabbitMQ支持消息应答。消费者发送一个消息应答,告诉RabbitMQ这个消息已经接收并且处理完毕了。RabbitMQ可以删除它了。

       如果一个消费者挂掉却没有发送应答,RabbitMQ会理解为这个消息没有处理完全,然后交给另一个消费者去重新处理。这样,你就可以确认即使消费者偶尔挂掉也不会不丢失任何消息了。

       没有任何消息超时限制;只有当消费者挂掉时,RabbitMQ才会重新投递。即使处理一条消息会花费很长的时间。

       消息应答是默认打开的。我们明确地把它们关掉了(autoAck=true)。现在将应答打开,一旦我们完成任务,消费者会自动发送消息应答。

boolean autoAck = false;
channel.basicConsume(QUEUE_NAME, autoAck, consumer);

       修改一下Worker.java

		channel.basicQos(1);//保证一次只分发一个
		// 创建队列消费者
		final Consumer consumer = new DefaultConsumer(channel) {
			  @Override
			  public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
			    String message = new String(body, "UTF-8");

			    System.out.println(" [x] Received '" + message + "'");
			    System.out.println(" [x] Proccessing... at " +new Date().toLocaleString());
			    try {
			    	for (char ch: message.toCharArray()) {
				        if (ch == '.') {
				        	Thread.sleep(1000);
				        }
				    }
				} catch (InterruptedException e) {
				} finally {
			      System.out.println(" [x] Done! at " +new Date().toLocaleString());
			      channel.basicAck(envelope.getDeliveryTag(), false);
			    }
			  }
			};
       我们还是运行1个生产者,2个消费者,在消息处理过程中,人为让一个消费者挂掉,然后会看到剩下的任务都会被另外的消费者执行。

       运行结果如下:


       如果你关闭了自动消息应答,手动也未设置应答,这是一个很简单错误,但是后果却是极其严重的。消息在分发出去以后,得不到回应,所以不会在内存中删除,结果RabbitMQ会越来越占用内存,最终的结果,你懂得。。。


Message durability(消息持久化)

       我们已经了解了如何确保即使消费者死亡,任务也不会丢失。但是如果RabbitMQ服务器停止,我们的任务仍将失去!
       当RabbitMQ退出或者崩溃,将会丢失队列和消息。除非你不要队列和消息。两件事儿必须保证消息不被丢失:我们必须把“队列”和“消息”设为持久化。 
    

boolean durable = true;
channel.queueDeclare("hello", durable, false, false, null);
       尽管这行代码是正确的,但他不会在我们当前的设置中起作用。因为我们已经定义了一个名叫hello的未持久化的队列。RabbitMQ不允许使用不同的参数设定重新定义已经存在的队列,并且会向尝试如此做的程序返回一个错误。一个快速的解决方案——就是声明一个不同名字的队列,比如task_queue。

       (当然,我们也可以登录到RabbitMQ的服务管理页面,RabbitMQ默认的端口是5672,管理页面默认端口是15672,页面地址为:http://localhost:15672,使用是用户名和密码登录。RabbitMQ的默认密码和用户名都是guest。点开“queue”那栏,可以看到队列列表,点击“hello”杜列,会展开队列的详细信息。把页面拉到最后,有一项“Delete / purge”,点开,点击“Delete”按钮,就可以把队列删除掉了。 然后再运行代码的时候,就会创建一个支持持久化的hello队列。)

       上述的代码需要在生产者和消费者都要作出同样的修改。

       在这一点上我们确信task_queue的队列不会丢失,即使RabbitMQ服务重启。现在我们需要将消息标记为持久性的——通过设置 MessageProperties(实现BasicProperties)为PERSISTENT_TEXT_PLAIN。

       现在你可以启动RabbitMQ服务器,执行一次生产者NewTask的程序,然后关闭服务器,再重新启动服务器,运行消费者Work做下实验。可以发现消费者依旧可以读出消息来。说明在RabbitMQ服务器关闭后,消息和队列信息都已经做了持久化。再次启动后,会重新加载到服务器中,消费者运行后,就可以正常的从队列中获取消息了。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
消息队列系列3 - 原理初探之RabbitMQ
RabbitMQ是使用Erlang语言来编写的,并且RabbitMQ是基于AMQP协议的。Erlang语言在数据交互方面性能优秀,有着和原生Socket一样的延迟,这也是RabbitMQ高性能的原因所在。可谓“人如其名”,RabbitMQ像兔子一样迅速。
28 0
RabbitMQ - 快速入门(一)
RabbitMQ - 快速入门(一)
55 0
RabbitMQ与Kafka选型对比(三)
RabbitMQ与Kafka选型对比(三)
70 0
rabbitmq系列(一)初识rabbitmq
假如我们开发了一个商品抢购网站。这个网站的目的就是在某一时间点进行抢购商品,同时要求用户注册,在注册的时候会同时给用户电话和邮箱中发送验证码,以便完成信息注册。传统做法应该是这样的。两种方式,并行即启用两个线程,当用户提交信息后,分别去发送邮件和发送短信。这种方式很明显比串行的方式更快
506 0
RabbitMQ快速入门
RabbitMQ是一种消息中间件,它接收和转发消息,可以理解为邮局。只是RabbitMQ接收,处理,转发的是二进制的数据,邮局处理的一般为纸。 基本概念 Producer(生产者): 发送消息的程序 Consumer(消费者):接收消息的程序 Queue(队列):像邮局的信箱,在RabbitMQ内部,同一个消息流只能存在一个Queue中,队列只受主机内存,磁盘的大小限制。
1236 0
轻松搞定RabbitMQ2:RabbitMQ基础与消息分发机制
轻松搞定RabbitMQ(一)——RabbitMQ基础知识+HelloWorld 本文是简单介绍一下RabbitMQ,参考官网上的教程。
1454 0
RabbitMQ的安装和配置化可视界面
RabbitMQ在windows下的安装 RabbitMQ 它依赖于Erlang,在window上安装时,需要先安装Erlang。 首先确定你的window电脑是32位还是64位,然后下载对应版本的Erlang软件。
1462 0
轻松搞定RabbitMQ(六)——主题
       翻译地址:http://www.rabbitmq.com/tutorials/tutorial-five-java.html        在上一篇博文中,我们进一步改良了日志系统。
814 0
+关注
龙轩8023
熟悉javaee开发,有多年支付领域的开发经验。关注开源~ httpclientUtil开源项目创建者。https://github.com/Arronlong
214
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载