消息何去何从

mandatory 和 immediate 是 channel . basicPublish 方法中的两个参数,它们都有 当消息传递过程中不可达目的地时将消息返回给生产者的功能。

当 mandatory 参数设为 true 时,交换器无法根据自身的类型和路由键找到一个符合条件 的队列,那么 RabbitMQ 会调用 Basic.Return 命令将消息返回给生产者。当 mandatory 参 数设置为 false 时,出现上述情形,则消息直接被丢弃。

生产者通过调用 channel . addReturnListener 来添加 ReturnListener 监昕器实现。

当 imrnediate 参数设为 true 时,如果交换器在将消息路由到队列时发现队列上并不存在 任何消费者,那么这条消息将不会存入队列中。当与路由键匹配的所有队列都没有消费者时, 该消息会通过 Basic . Return 返回至生产者。imrnediate 参数会影响镜像队列的性能, 增加了代码复杂性, 建议采用 TTL 和 DLX 的方法替代。

备份交换器,英文名称为 Altemate Exchange, 生产者在发送消息的时候如果不设置 mandatory 参数, 那么消息在未被路由的情况下将会丢失: 如果设置了 mandatory 参数,那么需要添加 ReturnListener 的编程逻辑,生产者的代码将变得复杂。如果既不想复杂化生产者的编程逻辑,又不想消息丢失,那么可以使用备份交换器, 这样可以将未被路由的消息存储在 RabbitMQ 中,再在需要的时候去处理这些消息。

可以通过在声明交换器(调用 channel.exchangeDeclare 方法)的时候添加 alternate-exchange 参数来实现,也可以通过策略 (Policy)的方式实现。 如果两者同时使用,则前者的优先级更高,会覆盖掉 Policy 的设置。

如果备份交换器和 mandatory 参数一起使用,那么 mandatory 参数无效。

过期时间 (TTL)

设置消息的 TTL

两种方法可以设置消息的 TTL, 第一种方法是通过队列属性设置,队列中所有消息都有相同的过期时间。第二种方法是对消息本身进行单独设置,每条消息的 TTL 可以不同。如 果两种方法一起使用,则消息的 TTL 以两者之间较小的那个数值为准。消息在队列中的生存时间一旦超过设置的 TTL 值时,就会变成"死信" (Dead Message)

1.通过队列属性设置

2.对消息本身进行单独设置

第一种一旦消息过期,就会从队列中抹去,第二种,即使消息过期,也不会马上从队列中抹去,因为每条消息是否过期是在即将投递到消费者之前判定的。

为什么这两种方法处理的方式不一样?因为第一种方法里,队列中己过期的消息肯定在队 列头部, RabbitMQ 只要定期从队头开始扫描是否有过期的消息即可。而第二种方法里,每条消息的过期时间不同,如果要删除所有过期消息势必要扫描整个队列,所以不如等到此消息即将 被消费时再判定是否过期, 如果过期再进行删除即可。

设置队列的 TTL

通过 channel . queueDeclare 方法中的 x-expires 参数可以控制队列被自动删除前处 于未使用状态的时间。未使用的意思是队列上没有任何的消费者,队列也没有被重新声明,并
且在过期时间段内也未调用过 Basic . Get 命令。

RabbitMQ 会确保在过期时间到达后将队列删除,但是不保障删除的动作有多及时 。在 RabbitMQ 重启后, 持久化的队列的过期时间会被重新计算。

Map<String, Object> args =new HashMap<String, Object>() ;

args . put( "x-expires" , 1800000);

channel . queueDeclare("myqueue" , false, false, false, args) ;

死信队列( Dead-Letter-Exchange)

当消息在一个队列中变成死信 (dead message) 之后,它能被重新被发送到另一个交换器中,这个交换器就是 DLX,绑定 DLX 的队列就称之为死信队列。

消息变成死信一般是由于以下几种情况:

  1. 消息被拒绝 (Basic.Reject/Basic .Nack),井且设置 requeue 参数为 false;
  2. 消息过期;
  3. 队列达到最大长度。

对于 RabbitMQ 来说, DLX 是一个非常有用的特性。 它可以处理异常情况下,消息不能够被消费者正确消费(消费者调用了 Basic.Nack 或者 Basic.Reject) 而被置入死信队列中
的情况,后续分析程序可以通过消费这个死信队列中的内容来分析当时所遇到的异常情况,进而可以改善和优化系统

延迟队列

一个应用中需要将每条消息都设置为 10 秒的延迟, 生产者通过 exchange.normal 这个交换器将发送的消息存储在 queue.normal 这个队列中。消费者 订阅的并非是 queue.normal 这个队列,而是 queue.dlx 这个队列。当消息从 queue.normal 这个队列中过期之后被存入 queue.dlx 这个队列中,消费者就恰巧消费到了延迟 10 秒的这条消息。

在真实应用中,对于延迟队列可以根据延迟时间的长短分为多个等级,一般分为 5 秒、 10秒、 30 秒、 1 分钟、 5 分钟、 10 分钟、 30 分钟、 1 小时这几个维度.

持久化

RabbitMQ的持久化分为三个部分:交换器的持久化、队列的持久化和消息的持久化。

交换器和队列的持久化是通过在声明时是将 durable 参数置为 true 实现的,消息的持久化是通过将消息的投递模式 (BasicProperties 中的 deliveryMode 属性)设置为 2 即可实现消息的持久化。

带来的问题:

1.影响性能,建议对可靠性不是很高的消息不持久化

2.设置了持久化,并不能保证数据百分之百不丢失,

  情况一,autoAck为true, 消费者接收消息后宕机了,数据会丢失,那么应该设置autoAck为false,手动确认。

情况二,持久化消息存入磁盘需要一定的时间,在这段时间内服务器宕机了,数据丢失,那么可以引入 RabbitMQ 的镜像队列机,相当于副本,提高高可用。

生产者确认

两种解决方式:

  • 通过事务机制实现:
  • 通过发送方确认 (publisher confirm) 机制实现。

事务机制

事务确实能够解决消息发送方和 RabbitMQ 之间消息确认的问题,只有消息成功被 RabbitMQ 接收,事务才能提交成功,否则便可在捕获异常之后进行事务回滚,与此同时可以进 行消息重发。但是使用事务机制会"吸干" RabbitMQ 的性能。

发送方确认机制

生产者将信道设置成 confmn (确认)模式,一旦信道进入 confmn 模式,所有在该信道上面发布的消息都会被指派一个唯一的 ID(从 l 开始),一旦消息被投递到所有匹配的队列之后, RabbitMQ 就会发送一个确认 (Basic.Ack) 给生产者(包含消息的唯一 ID),这就使得生产 者知晓消息已经正确到达了目的地了。如果消息和队列是可持久化的,那么确认消息会在消息写入磁盘之后发出。 RabbitMQ 回传给生产者的确认消息中的 deliveryTag 包含了确认消息的序号,此外 RabbitMQ 也可以设置 channel . basicAck 方法中的 multiple 参数,表示到 这个序号之前的所有消息都己经得到了处理。

Rabbitmq笔记二的更多相关文章

  1. springboot集成使用rabbitmq笔记(1.rabbitmq安装)

    使用rabbitmq笔记一 使用rabbitmq笔记二 使用rabbitmq笔记三 1.选择适配的版本,参考---https://www.rabbitmq.com/which-erlang.html ...

  2. springboot集成使用rabbitmq笔记(2.rabbitmq使用)

    使用rabbitmq笔记一 使用rabbitmq笔记二 使用rabbitmq笔记三 1.引入包 <dependencies> <dependency> <groupId& ...

  3. springboot集成使用rabbitmq笔记(3.基本过程)

    使用rabbitmq笔记一 使用rabbitmq笔记二 使用rabbitmq笔记三 1.AMQP协议 AMQP 0-9-1的工作过程如下图:消息(message)被发布者(publisher)发送给交 ...

  4. 《CMake实践》笔记二:INSTALL/CMAKE_INSTALL_PREFIX

    <CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...

  5. jQuery源码笔记(二):定义了一些变量和函数 jQuery = function(){}

    笔记(二)也分为三部分: 一. 介绍: 注释说明:v2.0.3版本.Sizzle选择器.MIT软件许可注释中的#的信息索引.查询地址(英文版)匿名函数自执行:window参数及undefined参数意 ...

  6. Mastering Web Application Development with AngularJS 读书笔记(二)

    第一章笔记 (二) 一.scopes的层级和事件系统(the eventing system) 在层级中管理的scopes可以被用做事件总线.AngularJS 允许我们去传播已经命名的事件用一种有效 ...

  7. Python 学习笔记二

    笔记二 :print 以及基本文件操作 笔记一已取消置顶链接地址 http://www.cnblogs.com/dzzy/p/5140899.html 暑假只是快速过了一遍python ,现在起开始仔 ...

  8. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  9. webpy使用笔记(二) session/sessionid的使用

    webpy使用笔记(二) session的使用 webpy使用系列之session的使用,虽然工作中使用的是django,但是自己并不喜欢那种大而全的东西~什么都给你准备好了,自己好像一个机器人一样赶 ...

随机推荐

  1. ArrayList源码分析超详细(转载)

    ArrayList源码分析超详细   ArrayList源码分析超详解 想要分析下源码是件好事,但是如何去进行分析呢?以我的例子来说,我进行源码分析的过程如下几步: 找到类:利用 IDEA 找到所需要 ...

  2. win10 localhost 解析为::1 的解决办法

    win10 localhost 解析为::1 的解决办法 学习了:https://blog.csdn.net/ambertian/article/details/70238020

  3. Dell R420 RAID建立以及系统安装

    http://thefallenheaven.blog.51cto.com/450907/1753472 Dell R420的RAID划分,以及系统安装 3块2T的盘,装好硬盘后开机,这里有3种方式去 ...

  4. win8 metro 自己写摄像头录像项目

    这是要求不适用CameraCaptureUI等使用系统自带的 camera  UI界面.要求我们自己写调用摄像头摄像的方法,如今我把我的程序贴下: UI界面的程序: <Page x:Class= ...

  5. yii2利用自带UploadedFile上传图片

    创建一个 models/UploadForm.php: <?php namespace app\models; use yii\base\Model; use yii\web\UploadedF ...

  6. 重载OverLoad。隐藏new

    <1> using System; using System.Collections.Generic; using System.Linq; using System.Text; name ...

  7. 数据结构-二叉树的遍历(类C语言描写叙述)

    遍历概念     所谓遍历(Traversal)是指沿着某条搜索路线.依次对树中每一个结点均做一次且仅做一次訪问.訪问结点所做的操作依赖于详细的应用问题. 遍历是二叉树上最重要的运算之中的一个,是二叉 ...

  8. 《TCP/IP具体解释》读书笔记(22章)-TCP的坚持定时器

    TCP通过让接收方指明希望从发送方接收的数据字节数(即窗体大小)来进行流量控制. 假设窗体大小为0会发生什么情况呢?这将有效阻止发送方传送数据,直到窗体变为非0为止. ACK的传输并不可靠,也就是说, ...

  9. 解决CentOS java环境不生效的问题

    查看当前java版本 [root@localhost jdk1.6.0_45]# java -version openjdk version "1.8.0_65" OpenJDK ...

  10. struts2多图片上传实例【转】

    原文地址:http://blog.csdn.net/java_cxrs/article/details/6004144 描述: 通过struts2实现多图片上传. 我使用的版本是2.2.1,使用的包有 ...