夫天地者,万物之逆旅;光阴者,百代之过客。而浮生若梦,为欢几何?
RabbitMQ 入门篇之—延迟队列

延迟队列使用场景

1、业务失败后的重试

2、定时任务

3、电商中未完成支付的订单撤销

类似的场景还有很多,在RabbitMQ中要实现一个延迟队列需要消息的TTL和死信的Exchange这两个特性相互配合支持。

TTL(Time To Live)

RabbitMQ可以对队列和消息设置TTL,来控制消息的生存时间。如果超时,那么就认为这个消息死了,我们称为死信。

下面是TTL关键实现代码:

IModel model = getChannel(durable, queueName);
            var args = new Dictionary<string, object>();
            //args.Add("x-expires", 1000 * 30);//设置队列 30s 过期,过期后将自动丢弃
            //args.Add("x-message-ttl", 1000*30);//设置队列中消息 30s 钟过期,过期后消息将自动丢弃
            model.QueueDeclare(queueName, durable, false, false, args);
            var properties = model.CreateBasicProperties();
            properties.Expiration = "30000"; //也可以设置单条消息的过期时间
            for (int i = 1; i < 2; i++)
            {
                byte[] messageBodyBytes = Encoding.UTF8.GetBytes("Hello limitcode :" + i);
                model.BasicPublish("", queueName, properties, messageBodyBytes);//推送消息
                Console.WriteLine("已发送 {0} 条消息", i);
                System.Threading.Thread.Sleep(2000);
            }

上面的消息在超时时间内没有被消费,将自动变为死信,如果没有为消息设置死信队列,那么消息将被丢弃。

DLE(Dead Letter Exchanges)

RabbitMQ可以设置队列的x-dead-letter-exchange和x-dead-letter-routing-key属性,当队列中消息变为dead letter后,消息将被按照路由规则转发到指定队列。如果一个消息要成为死信,有下列三种情况:

1、队列或消息的TTL过期

2、队列达到最大长度,旧消息将被丢弃

3、消息被消费端拒绝(basic.reject or basic.nack)并且requeue=false

下面是将TTL过期的消息转发到死信队列的关键代码:

var queueName = "TTLQueue";
            var dleExchange = "DLEExchange";// 定义死信交换机名称
            var dleQueueName = "DLEQueue";// 定义死信队列名称
            var dleRouteKey = dleQueueName;// 路由和队列名称一致
            IModel model = getChannel(durable, queueName);
            model.ExchangeDeclare(dleExchange, "direct");// 创建死信交换机
            model.QueueDeclare(dleQueueName, durable, false, false, null);// 声明死信队列
            model.QueueBind(dleQueueName, dleExchange, dleRouteKey);// 将死信交换机和队列绑定

            var args = new Dictionary<string, object>();
            args.Add("x-message-ttl", 1000*10);//设置队列中消息 10s 钟过期,过期后消息将自动丢弃
            args.Add("x-dead-letter-exchange", dleExchange);// 设置消息过期后的转发交换机
            args.Add("x-dead-letter-routing-key", dleRouteKey);// 设置消息过期后的转发路由
            model.QueueDeclare(queueName, durable, false, false, args);

            var properties = model.CreateBasicProperties();
            for (int i = 1; i < 2; i++)
            {
                byte[] messageBodyBytes = Encoding.UTF8.GetBytes("Hello limitcode :" + i);
                model.BasicPublish("", queueName, properties, messageBodyBytes);//推送消息
                Console.WriteLine("已发送 {0} 条消息", i);
                System.Threading.Thread.Sleep(2000);
            }

通过TTL和DLE的结合,我们可以创建一个RabbitMQ延迟队列的功能。

作者:暗夜余晖

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

3

支持

0

反对

posted @2018-9-12  拜读(1450)

评论列表

评论内容:



喜欢请打赏

支付宝 微信

请放心支付