com网站免费注册,西安网站开发,时光捕手 wordpress,医药网站建设价格#xff08;一#xff09;TTL
1.TTL概念 TTL又叫过期时间
RabbitMQ可以对队列和消息设置TTL#xff0c;当消息到达过期时间还没有被消费时就会自动删除
注#xff1a;这里我们说的对队列设置TTL,是对队列上的消息设置TTL并不是对队列本身#xff0c;不是说队列过期时间…一TTL
1.TTL概念 TTL又叫过期时间
RabbitMQ可以对队列和消息设置TTL当消息到达过期时间还没有被消费时就会自动删除
注这里我们说的对队列设置TTL,是对队列上的消息设置TTL并不是对队列本身不是说队列过期时间到了队列被删除而是消息到达此队列后会给他设定一个过期时间这个时间到了消息会删除不是队列删除如果同时此消息本身带有TTL过期时间按短的来
2.设置消息的TTL 那我们说可以对队列和消息设置TTL 那我们现在来先写对每条消息设置TTL(就是针对每一条消息设置消息的expiration参数单位是毫秒)
那我们来看生产者代码这里配置文件不需要去更改
RequestMapping(ttl)public String TTLPro(){String s1ttl test;Message messagenew Message(s1.getBytes(StandardCharsets.UTF_8));message.getMessageProperties().setExpiration(10000);RabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE,ttl,message);return 发送成功;} 我们来看现象我这里设置过期时间为10s按理说到达队列后如果10s钟还没有被消费掉就会自动过期 10s后 如果我们不设置TTL就表示消息不会过期如果设置为0的化就表示除非此时可以直接将消息给消费者否者就会被丢弃 3.设置队列的TTL 设置队列的TTL是比较简单的但是注意我们队列如果存在的话我们是不可以直接改代码然后更改队列的配置信息的同时交换机也是这样如果我们想改可以再声明个队列或者把队列先删了再创建此时队列上的消息会丢失 设置队列过期时间只需要在队列上配置ttl属性就可以我这里设置了5s 此时我们队列的特性就又多了个TTL 然后我们继续向接口发送消息
5s后就变成了真的是5s 骗人是g 4.两者区别 设置队列TTL属性的方法一旦消息过期就会立即从队列中删除 设置消息TTL的方法一旦消息过期且不是队列中第一个消息消息并不会立即删除而是在要发送给消费者之前进行判定如果过期了再删 那我们就有疑问了这是为什么呢 本质上是为了提高性能因为设置队列的过期时间他们消息的最长存在时间就是队列的过期时间所有消息的存在时间都小于等于队列过期时间所以此时队列中已过期的元素大部分都在队列头部RabbitMQ只需要定期从队头开始扫描是否有过期消息即可 而设置消息TTL每条消息的过期时间都不同如果想要删除所有过期时间就需要扫描整个队列很影响性能所以不如等到用到了此消息再判定是否过期如果过期了再删除
二死信
1.死信概念 死信就是因为一些原因包括消息过期消息被拒绝接收队列达到最大长度无法被消费的消息。 那既然有这些无法被处理的信息那一定就有存储他们的队列有队列就要有交换机那么这个队列就叫做死信队列DLQ这个交换机就叫死信交换机DLX 本质上与正常的交换机和队列没什么区别 消息变成死信后会被发送到死信交换机然后由死信交换机绑定到死信队列中
2.代码演示
首先我们要声明一个死信队列和死信交换机进行绑定哪至于正常的队列我们就用刚刚的TTL为5的队列吧 Bean(ttlExchange)public Exchange ttlExchange(){return ExchangeBuilder.directExchange(Constants.TTL_EXCHANGE).durable(true).build();}Bean(ttlQueue)public Queue ttlQueue(){return QueueBuilder.durable(Constants.TTL_QUEUE).ttl(5000).deadLetterExchange(Constants.DEAD_EXCHANGE).deadLetterRoutingKey(dead).build();}Bean(ttlBind)public Binding ttlBind(Qualifier(ttlExchange) Exchange ackExchange,Qualifier(ttlQueue) Queue queue){return BindingBuilder.bind(queue).to(ackExchange).with(ttl).noargs();}Bean(deadExchange)public Exchange deadExchange(){return ExchangeBuilder.directExchange(Constants.DEAD_EXCHANGE).durable(true).build();}Bean(deadQueue)public Queue deadQueue(){return QueueBuilder.durable(Constants.DEAD_QUEUE).build();}Bean(deadBind)public Binding deadBind(Qualifier(deadExchange) Exchange ackExchange,Qualifier(deadQueue) Queue queue){return BindingBuilder.bind(queue).to(ackExchange).with(dead).noargs();}
然后我们发送消息等待5s看一下 然后我们看看刚才绑定死信交换机的那个队列特征
我们发现又多了两个特征
那验证完TTL过后我们来看消息被拒绝的情况
首先我们要把消息确认模式改成手动确认然后拒绝接收消息 RabbitListener(queues Constants.TTL_QUEUE)public void ListenerQueue2(Message message,Channel channel) throws IOException {long Tagmessage.getMessageProperties().getDeliveryTag();try {System.out.println(接收到消息: new String(message.getBody()) TagID: Tag);int num3/0; //模拟失败channel.basicAck(Tag,false);System.out.println(处理完成);}catch (Exception e){channel.basicReject(Tag,false);}}
然后我们调用接口看死信队列我们发现确实多了一条死信消息 那第三种产生死信的消息是队列满了那我们就需要更改一下我们队列
Bean(ttlQueue)public Queue ttlQueue(){return QueueBuilder.durable(Constants.TTL_QUEUE).ttl(5000).deadLetterExchange(Constants.DEAD_EXCHANGE).deadLetterRoutingKey(dead).maxLength(5l).build();} 此时我们注意我们要的是long类型如果传错了会给我们报错的 那我们再来看这个队列 我们发现又多了一个特征
我们到此已经给队列设置5个特征了我们来分别看一下
1D设置队列为持久化的
2TTL设置队列的过期时间
3Lim设置队列的最大长度
4DLX设置了死信交换机
5DLK设置了死信RoutingKey
3.死信面试题
死信概念死信来源死信场景
前两个我们都说过了这里主要说一下死信的应用场景
比如我们用户支付订单支付系统会给我们订单系统返回当前订单的支付状态 为了保障支付信息不丢失需要使用死信队列机制当消息消费异常时会放到死信队列中有可能存在用户支付但是消息没有被消费或者异常拒绝的情况此时我们放到死信队列中再对这个数据进行处理可能是人工确认
还有一些应用场景包括
消息丢弃直接丢弃这些无法处理的消息避免他们占用系统资源
日志收集将死信消息作为日志收集用于后续分析和定位