RabbitMQ延时队列


想要实现RabbitMQ延时队列有两种方式

一:TTL(消息过期) + 死信队列

TTL + 死信队列的实现方式主要是,TTL 来控制延时时间,等到延时时间过期,消息就会被扔到死信队列来处理,从而达到延时队列的效果。

TTL 过期时间有两种设置方式:

单独指定消息的过期时间

@GetMapping("/topic/sendMsg2")
	public String topicSendMsg2(){
		String msg = "hello World";
		// 对每条消息设置过期时间
		MessageProperties messageProperties = new MessageProperties();
		messageProperties.setExpiration("20000"); // 时间单位为 毫秒
		Message message = new Message(msg.getBytes(),messageProperties);
		System.out.println("topicSendMsg2{}"+  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		rabbitTemplate.convertAndSend("test_topic_exchange_name","test_topic_routing_name",message);
		return "ok~";
	}

优点:每条消息的过期时间都可以自由的控制,控制粒度小。
缺点:没有统一的控制,如果过期时间一致的话,则需要每条都写过期配置
消息推送到队列后,如果指定时间内没有被消费,则会自动过期。

注意:
RabbitMQ只会对队列头部的消息进行过期淘汰。如果单独给消息设置TTL,先入队列的消息过期时间如果设置比较长,后入队列的设置时间比较短。会造成消息不会及时地过期淘汰,导致消息的堆积。

给队列设置消息过期时间,队列中的所有消息都有同样的过期时间。

// 正常的队列
	@Bean
	public Queue createTopicQueue(){
		Map<String, Object> arguments = new HashMap<>(2);
		// 设置过期时间,对 队列设置统一的过期时间,单位为 毫秒
		arguments.put("x-message-ttl",30000);

		// 绑定死信交换机
		arguments.put("x-dead-letter-exchange", TEST_DEAD_TOPIC_EXCHANGE_NAME);
		// 绑定死信的路由key
		arguments.put("x-dead-letter-routing-key", TEST_DEAD_TOPIC_ROUTING_NAME);
		// 绑定死信队列的交换机和路由
		return new Queue(TEST_TOPIC_QUEUE_NAME,true,false,false,arguments);
	}

对队列设置过期时间,这队列的每条消息的过期时间都一致,
注意:如果两个过期时间都设置的话,则以时间最短的那个为主。

二:RabbitMQ插件使用

Docker 安装RabbitMQ的延时插件

下载插件

根据自己的版本下载对应的插件
rabbitmq-delayed-message-exchange
在这里插入图片描述

安装

上传到服务器的/zhanghang/rabbitmq/plugs文件夹下,然后进行如下操作
在这里插入图片描述
在这里插入图片描述

#拷贝到rabbitmq容器 773067241f96 中
docker cp /zhanghang/rabbitmq/plugs/rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez rabbit:/plugins
# rabbit 是我启动的rabbitmq的别名

#进入容器
docker exec -it rabbit /bin/bash

#启用插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange

#查看
rabbitmq-plugins list

#重新启动容器
docker restart rabbit

在这里插入图片描述
在这里插入图片描述

使用

@Configuration
public class TopicRabbitConfig1 {
	// 正常的topic 队列
	public static final String TEST_TOPIC_EXCHANGE_NAME = "test_topic_exchange_name1";
	public static final String TEST_TOPIC_QUEUE_NAME = "test_topic_queue_name1";
	public static final String TEST_TOPIC_ROUTING_NAME = "test_topic_routing_name1";


	// 正常的队列
	@Bean
	public Queue createTopicQueue1(){
		return new Queue(TEST_TOPIC_QUEUE_NAME,true,false,false);
	}

    // 定义延时的交换机
	@Bean
	public CustomExchange createTopicExchange1(){
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-delayed-type", "direct");
		// 参数说明:
		// name:    交换机名称
        // type:  交换机类型
		// durable: 是否持久化
		// autoDelete: 是否自动删除
        // arguments:  配置
		return new CustomExchange(TEST_TOPIC_EXCHANGE_NAME,"x-delayed-message",true,false,args);
	}

	@Bean
	public Binding createTopicBinding1(){
		return BindingBuilder.bind(createTopicQueue1()).to(createTopicExchange1()).with(TEST_TOPIC_ROUTING_NAME).noargs();
	}

}
// 发送消息
@GetMapping("/topic/sendMsg2")
	public String topicSendMsg2(){
		String msg = "hello World";
		// 对每条消息设置过期时间
		MessageProperties messageProperties = new MessageProperties();
        // 设置延时时长,单位为毫秒
		messageProperties.setDelay(1 * 60 * 1000);
		Message message = new Message(msg.getBytes(),messageProperties);
		System.out.println("topicSendMsg2{}"+  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		rabbitTemplate.convertAndSend("test_topic_exchange_name1","test_topic_routing_name1",message);
		return "ok~";
	}

测试发现经过一分钟后消费者收到消息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值