消息何去何从

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. Topcoder 2015_1C

    A:大水题; B:求一颗树中,有多少条路径 不存在路径中一点是另外一点的祖先,(后面废话说了很多) 其实一个点 可以到它本身也可以是一条路径结论是:统计叶子的节点.(真简单粗暴 C:题目不说,说也说不 ...

  2. [洛谷U22157]刷水题(数位dp)(hash)

    题目背景 做正经题是不可能做正经题的,这辈子都不可能做正经题的,毒瘤题又不会做毒瘤题,就是水题这种东西,才维持了蒟蒻的信心: 题目描述 这里有N+1 道水题,编号分别为0 ~N+1 ,每道水题都有它自 ...

  3. java学习——关于java课件上动手动脑问题简单的分析

    问题一:关于以下的代码为什么会产生错误的问题的简单分析. 第一个动手动脑提供了一下的代码,可以发现,在Foo的这个类中只定义了一个Foo(int)类型的构造函数,在之前的学习工程中,我们并没有接触到j ...

  4. 转:Linux性能评测工具之一:gprof篇

    1 简介 改进应用程序的性能是一项非常耗时耗力的工作,但是究竟程序中是哪些函数消耗掉了大部分执行时间,这通常都不是非常明显的.GNU 编译器工具包所提供了一种剖析工具 GNU profiler(gpr ...

  5. MD5加密Java工具类

    原文:http://www.open-open.com/code/view/1421764946296 import java.security.MessageDigest; public class ...

  6. struts2 自己定义表单

    自己定义表单一定会涉及<s:iterator/>迭代,一个复杂的自己定义表单可能会嵌套n多层迭代. 比方一个自己定义一个问卷调查页面涉及3个模型:一个Survey代表一个调查.一个Page ...

  7. Feign简介

    Feign简介

  8. Linux上设置RAID 10

    RAID 10(又叫RAID 1+0或镜像条带)阵列结合了RAID 0和RAID 1两者的功能特性,从而提供了高性能.容错的磁盘输入/输出操作.在RAID 0中,读取/写入操作跨多个驱动器并路执行:在 ...

  9. ADO.NET(OleDb)读取Excel表格时的一个BUG

    如果我们有例如以下一个Excel表格:    如今要使用C#程序读取其内容: using System;  using System.Data.OleDb;    namespace Skyiv.Be ...

  10. Binder IPC的权限控制

    PS:个人理解:当进程1通过Binder调用组件2时,会将进程1的pid及uid赋给组件2,并检测进程1的pid及uid是否有权限调用组件2.而后组件2需要调用组件3,此时组件2保存的pid及uid为 ...