转自 http://blog.csdn.net/xiaoxian8023/article/details/48710653

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

Message acknowledgment(消息应答)

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

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

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

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

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

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

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

修改一下Worker.java

  1. channel.basicQos(1);//保证一次只分发一个
  2. // 创建队列消费者
  3. final Consumer consumer = new DefaultConsumer(channel) {
  4. @Override
  5. public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
  6. String message = new String(body, "UTF-8");
  7. System.out.println(" [x] Received '" + message + "'");
  8. System.out.println(" [x] Proccessing... at " +new Date().toLocaleString());
  9. try {
  10. for (char ch: message.toCharArray()) {
  11. if (ch == '.') {
  12. Thread.sleep(1000);
  13. }
  14. }
  15. } catch (InterruptedException e) {
  16. } finally {
  17. System.out.println(" [x] Done! at " +new Date().toLocaleString());
  18. channel.basicAck(envelope.getDeliveryTag(), false);
  19. }
  20. }
  21. };

我们还是运行1个生产者,2个消费者,在消息处理过程中,人为让一个消费者挂掉,然后会看到剩下的任务都会被另外的消费者执行。

运行结果如下:


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

Message durability(消息持久化)

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

  1. boolean durable = true;
  2. 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服务器关闭后,消息和队列信息都已经做了持久化。再次启动后,会重新加载到服务器中,消费者运行后,就可以正常的从队列中获取消息了。

轻松搞定RabbitMQ(三)——消息应答与消息持久化的更多相关文章

  1. 轻松搞定RabbitMQ(六)——主题

    转自 http://blog.csdn.net/xiaoxian8023/article/details/48806871 翻译地址:http://www.rabbitmq.com/tutorials ...

  2. 轻松搞定RabbitMQ(二)——工作队列之消息分发机制

    转自 http://blog.csdn.net/xiaoxian8023/article/details/48681987 上一篇博文中简单介绍了一下RabbitMQ的基础知识,并写了一个经典语言入门 ...

  3. 轻松搞定RabbitMQ(一)——RabbitMQ基础知识+HelloWorld

    转自 http://blog.csdn.net/xiaoxian8023/article/details/48679609 本文是简单介绍一下RabbitMQ,参考官网上的教程.同时加入了一些自己的理 ...

  4. 轻松搞定RabbitMQ(五)——路由选择

    转自 http://blog.csdn.net/xiaoxian8023/article/details/48733249 翻译地址:http://www.rabbitmq.com/tutorials ...

  5. 轻松搞定RabbitMQ(四)——发布/订阅

    转自 http://blog.csdn.net/xiaoxian8023/article/details/48729479 翻译地址:http://www.rabbitmq.com/tutorials ...

  6. 春节过后就是金三银四求职季,分享几个Java面试妙招,轻松搞定HR!

    春节过后就是金三银四,分享几个Java面试妙招,轻松搞定HR! 2020年了,先祝大家新年快乐! 今年IT职位依然相当热门,特别是Java开发岗位.软件开发人才在今年将有大量的就业机会.春节过后,金三 ...

  7. Webcast / 技术小视频制作方法——自己动手录制video轻松搞定

    Webcast / 技术小视频制作方法——自己动手录制video轻松搞定 http://blog.sina.com.cn/s/blog_67d387490100wdnh.html 最近申请加入MSP的 ...

  8. 【微服务】之三:从零开始,轻松搞定SpringCloud微服务-配置中心

    在整个微服务体系中,除了注册中心具有非常重要的意义之外,还有一个注册中心.注册中心作为管理在整个项目群的配置文件及动态参数的重要载体服务.Spring Cloud体系的子项目中,Spring Clou ...

  9. 【转】轻松搞定FTP之FlashFxp全攻略

    转载网址:http://www.newhua.com/2008/0603/39163.shtml 轻松搞定FTP之FlashFxp全攻略 导读: FlashFXP是一款功能强大的FXP/FTP软件,融 ...

随机推荐

  1. POJ 1315 Don't Get Rooked

    Don't Get Rooked Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2086   Accepted: 1325 ...

  2. 详解keepalived配置和使用

    标签:keepalived 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://lanlian.blog.51cto.com/6790 ...

  3. java maven项目testng执行时使用的是test-classes下的文件,共享main下方resource的配置

    在pom.xml中配置 <build> <testResources> <testResource> <directory>${project.base ...

  4. 最新版浏览器报错net::ERR_INSECURE_RESPONSE原因

    访问的网址与接口请求的域名不一致,新版的chrome浏览器出于安全的考虑会将请求进行拦截,并报错net::ERR_INSECURE_RESPONSE

  5. 【CF1028C】Rectangles(线段树)

    题意: n<=1e5,abs(x[i]),abs(y[i]<=1e9 思路:这是正解 离散后线段树强打,数据结构越学越傻 #include<cstdio> #include&l ...

  6. app_data中的数据库使用

    原文发布时间为:2008-07-24 -- 来源于本人的百度文章 [由搬家工具导入] ASP.NET中利用VWD操作数据库 建立本地数据库   你可以轻易地在Visual Studio的Web应用程序 ...

  7. set up trace code tool

    這以 GNU GLOBAL 6.5.6 為示範 1: install GNU GLOBAL https://www.gnu.org/software/global/download.html sudo ...

  8. Python入门--17--pickle

    pickle模块,实际用途也很简单.单一,主要用于保存列表(list),元祖(Tuple),字典(dictionary) 当然,一定是大的列表.字典什么的,成千上万行的字典.列表,才能凸显出它的用武之 ...

  9. 记一次安装centos7及gnome桌面

    https://blog.csdn.net/bingbingtea/article/details/79553669

  10. CocoaPods | iOS详细使用说明

    一:介绍 在iOS开发中,经常会使用到第三方库,[CocoaPods](https://github.com/CocoaPods/CocoaPods)可以用来方便的统一管理这些第三方库. 下面就和大家 ...