array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 RabbitMQ死信队列+延时队列 - 爱码网

原文:http://www.cnblogs.com/williamwsj/p/8108970.html

参考文献:https://www.rabbitmq.com/dlx.html

死信,顾名思义,就是死掉的消息,死掉的消息是会被一般的队列丢弃的。如果这些消息很重要,而我们又需要,怎么办?凡事都有一个退路,现在就有一种方法可将这些死信消息存下来,那就是DLX(Dead Letter Exchanges)。DLX是专门用来存储死信消息到指定队列中的一种交换机。需要在声明队列时指定DLX和死信存放队列的路由Key,因为RabbitMQ是通过Exchange去匹配路由key寻找队列的。

死信消息是怎么产生的呢?

1、消息被拒(basic.reject or basic.nack)并且没有重新入队(requeue=false);

2、消息在队列中过期,即当前消息在队列中的存活时间已经超过了预先设置的TTL(Time To Live)时间;

3、当前队列中的消息数量已经超过最大长度。

消息进入死信队列的过程:消息 -> 队列 (触发以上条件)-> DLX交换机 -> DLK队列

以上是对死信及其去向的介绍,接下来上代码!

 

 var factory = new ConnectionFactory() { HostName = "localhost",UserName="ty2017",Password="123456",VirtualHost="log" };
            using (var connection = factory.CreateConnection()) {
                using (var channel = connection.CreateModel()) {                    
                    //声明一个direct类型的交换机,用来当做某个队列的死信交换机(DLX)
                    channel.ExchangeDeclare("e.log.dead", //交换机名称
                                            "direct"); //交换机类型
                    //声明一个队列,用来存放死信消息
                    channel.QueueDeclare(queue: "q.log.dead",
                                         durable: false,
                                         exclusive: false,
                                         autoDelete: false,
                                         arguments: null);

                    //声明一个队列,并指定该队列的DLX和死信路由key,且还需要设置TTL(消息存活时间)
                    channel.QueueDeclare(queue: "q.log.error",
                                         durable: false,
                                         exclusive: false,
                                         autoDelete: false,
                                         arguments: new Dictionary<string, object> {
                                         { "x-dead-letter-exchange","e.log.dead"}, //设置当前队列的DLX
                                         { "x-dead-letter-routing-key","dead"}, //设置DLX的路由key,DLX会根据该值去找到死信消息存放的队列
                                         { "x-message-ttl",10000} //设置消息的存活时间,即过期时间
                                         });
                                         
                    //将DLX和死信存放队列绑定,并产生一个路由key
                    channel.QueueBind("q.log.dead", "e.log.dead", "dead");
                    //绑定消息队列
                    channel.QueueBind("q.log.error", //队列名称
                                      "e.log",      //交换机名称
                                      "log.error");  //自定义的RoutingKey
                    //需要发送的消息
                    var body = Encoding.UTF8.GetBytes(param.Data);

                    var properties = channel.CreateBasicProperties();
                    //设置消息持久化
                    properties.SetPersistent(true);
                    //发布消息
                    channel.BasicPublish(exchange: "e.log",
                                         routingKey: "log.error",
                                         basicProperties: properties,
                                         body: body);
                }
            }

 

解释一下代码

1.有一个名为q.log.error的消息队列,该队列中消息的过期时间为10000毫秒;

2.有一个名为e.log.dead的交换机(Exchange),其类型是direct;

3.有一个名为q.log.dead的消息队列,等会我们会将死信消息存入该队列中;

4.将e.log.dead交换机和q.log.dead队列绑定,并产生一个名为dead的RoutingKey;

5.指定e.log.dead交换机为队列q.log.error的DLX(死信交换机);

6.指定dead为DLX的RoutingKey;

7.如果q.log.error队列中产生了死信,RabbitMQ则会将死信消息发送给e.log.dead交换机,该交换机再通过dead(设置的DLX的RoutingKey)去找到q.log.dead队列,并将该死信消息存放进去。

其实DLX是一个普通的交换机,只是我们在声明队列的时候,将其指定为该队列的死信交换机(x-dead-letter-exchange)而已,也就是死信消息的去处。有交换机就需要有一个RoutingKey,因此,我们在设置DLX的时候,也需要一并设置x-dead-letter-routing-key参数。

 

让我们看一下web管理工具中的情况:

消息进入死信队列的过程:消息 -> q.log.error队列 (过期TTL)-> e.log.dead交换机DLX (通过DLK) -> q.log.dead队列

将q.log.dead队列绑定到e.log.dead交换机

在web管理工具中创建q.log.error队列时设置属性 : 

x-message-ttl(消息超时时间TTL)

x-dead-letter-exchange=e.log.dead(对应死信交换机DXL)

x-dead-letter-routing-key=q.log.dead(进入死信交换机后的路由键,即死信最终路由到的队列DLK)

 

消息过期之前,消息保留在q.log.error队列中。TTL表示当前队列设置了消息过期时间,DLX表示当前队列设置了死信交换机,DLK表示当前队列设置了死信交换机对应的RoutingKey(消息发到死信交换机后,路由到哪个queue中)。具体信息如下图所示:

 RabbitMQ死信队列+延时队列

消息过期之后就变为了死信消息,消息就通过e.log.dead交换机跑到了q.log.dead队列中。如下图所示:

RabbitMQ死信队列+延时队列

  web管理工具中测试发送接收

发送:

Exchange页面点击相应的交换机,进入交换机信息页面,找到 Publish message,设置 路由键+内容(Payload)发送消息进入此交换机

RabbitMQ死信队列+延时队列

接收:

Queues页面点击路由键对应的接收队列(先绑定交换机),进入队列信息页面,找到 Get messages,设置ack模式点击Get message,显示接收的消息内容(四种ack模式依次:Nack+重新入队;ACK;拒绝+重新入队;拒绝+不重新入队)

重新入队会放回队列首,需要谨慎避免无法消费造成死循环

https://blog.csdn.net/shanchahua123456/article/details/84328729

RabbitMQ死信队列+延时队列RabbitMQ死信队列+延时队列

 

  

 

相关文章: