TTL队列消息与死信队列

TTL概念

TTL是time to live的缩写,生存时间

消费者队列中设置TTL

RabbitMQ支持消息的过期时间,消息发送时可以指定,从消息入队列开始计算,只要超过队列的超时时间配置,消息就会自动清除

消费端代码

Map<String, Object> args = new HashMap<String, Object>();

args.put("x-message-ttl", 60000);

channel.queueDeclare("myqueue", false, false, false, args);

public class Consumer {

	public static void main(String[] args) throws Exception {
		
		//1 创建一个ConnectionFactory, 并进行配置
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost("192.168.17.17");
		connectionFactory.setPort(5672);
		connectionFactory.setVirtualHost("/");
		
		//2 通过连接工厂创建连接
		Connection connection = connectionFactory.newConnection();
		
		//3 通过connection创建一个Channel
		Channel channel = connection.createChannel();
		
		//4 声明(创建)一个队列
		String queueName = "testttl";


		//队列中设置ttl,如果20秒内不消费,将自动删除该消息
		Map<String, Object> argttl = new HashMap<String, Object>();
		argttl.put("x-message-ttl", 20000);
		channel.queueDeclare(queueName, true, false, false, argttl);
		
		//5 创建消费者
		QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
		
		//6 设置Channel
		//1、消费的队列2、是否自动签收,当消费者接受后,消费端给broker回送一条ack的消息,告诉收到,
		//如果false,需要代码上指定,一般是false,处理完消息后,手工返回 3、消费者对象
		channel.basicConsume(queueName, true, queueingConsumer);
		
		while(true){
			//7 获取消息
			Delivery delivery = queueingConsumer.nextDelivery();
			String msg = new String(delivery.getBody());
			System.err.println("消费端: " + msg);
			//Envelope envelope = delivery.getEnvelope();  //可以获得消息的队列和exchange
		}
		
	}
}

生产者每条消息设置TTL

TTL 设置可以具体到每一条 message 本身,只要在通过 basic.publish 命令发送 message 时设置 expiration 字段

生产者代码

示例 publish 了最多能在 queue 中存活 60 秒的 message : 

byte[] messageBodyBytes = "Hello, world!".getBytes();

AMQP.BasicProperties properties = new AMQP.BasicProperties();

properties.setExpiration("60000");

channel.basicPublish("myexchange", "routingkey", properties, messageBodyBytes);

public class Procuder {

	
	public static void main(String[] args) throws Exception {
		//1 创建一个ConnectionFactory, 并进行配置
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost("192.168.17.17");
		connectionFactory.setPort(5672);
		connectionFactory.setVirtualHost("/");

		//2 通过连接工厂创建连接
		Connection connection = connectionFactory.newConnection();
		
		//3 通过connection创建一个Channel
		Channel channel = connection.createChannel();
		
		//4 通过Channel发送数据
		for(int i=0; i < 5; i++){
			String msg = "Hello RabbitMQ!";
			//1 exchange   2 routingKey  3 BasicProperties(修饰消息的附加属性) 4、body(消息的实体)
			//如果exchange为空,使用默认的路由,此时routingkey和queue是一样的名称,如果有一样的名称才能发送成功
			
			AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
			.deliveryMode(2)
			.contentEncoding("UTF-8")
			.expiration("20000")
			.build();
			channel.basicPublish("", "testttl",  properties, msg.getBytes());
		}

		//5 记得要关闭相关的连接
		channel.close();
		connection.close();
		
		System.out.println("success");
	}
}

当同时指定了 queue 和 message 的 TTL 值,则两者中较小的那个才会起作用。

死信队列

当消息在一个队列中变成死信(消息没有任何消费者去消费)之后,它能被重新publish到另一个Exchange,这个Exchange就是DLX

DLX也是一个正常的Exchange,和一般的Exchange没什么区别,它能在任何的队列上被指定,实际就是设置某个队列的属性

当这个队列中有死信时,RabbitMQ就会自动将这个消息重新发布到设置的Exchange上去,进而路由到另一个队列

消息变为死信的几种情况

消息被拒绝(basic.rejec/basic.nack)且requeue=false

channel.basicNack(envelope.getDeliveryTag(), false, false)

TTL过期

队列超时设置或消息的超时设置

队列达到最长长度

死信队列的设置

设置死信队列的exchange和queue,然后进行绑定

Exchange:dlx.exchange

Queue:dxs.queue

RoutingKey:#

正常声明交换机、队列、绑定,只不过我们需要在队列加上一个参数:arguments.put(“x-dead-letter-exchange”,” dlx.exchange”);

生产端代码

                            AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()

                                               .deliveryMode(2)

                                               .contentEncoding("UTF-8")

                                               .expiration("10000")

                                               .build();

                            channel.basicPublish(exchange, routingKey,   properties, msg.getBytes());

public class Producer {

	
	public static void main(String[] args) throws Exception {
		
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost("192.168.17.17");
		connectionFactory.setPort(5672);
		connectionFactory.setVirtualHost("/");
		
		Connection connection = connectionFactory.newConnection();
		Channel channel = connection.createChannel();
		
		String exchange = "test_dlx_exchange";
		String routingKey = "dlx.save";
		
		String msg = "Hello RabbitMQ DLX Message";
		
		for(int i =0; i<1; i ++){
			
			AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
					.deliveryMode(2)
					.contentEncoding("UTF-8")
					.expiration("10000")
					.build();
			channel.basicPublish(exchange, routingKey,   properties, msg.getBytes());
		}
		
	}
}

消费端代码

                   channel.exchangeDeclare(exchangeName, "topic", true, false, null);

                  

                   Map<String, Object> agruments = new HashMap<String, Object>();

                   agruments.put("x-dead-letter-exchange", "dlx.exchange");

                   //这个agruments属性,要设置到声明队列上

                   channel.queueDeclare(queueName, true, false, false, agruments);

                   channel.queueBind(queueName, exchangeName, routingKey);

                  

                   //要进行死信队列的声明:

                   channel.exchangeDeclare("dlx.exchange", "topic", true, false, null);

                   channel.queueDeclare("dlx.queue", true, false, false, null);

                   channel.queueBind("dlx.queue", "dlx.exchange", "#");

                   //#

                   channel.basicConsume(queueName, true, new MyConsumer(channel));


public class Consumer {

	
	public static void main(String[] args) throws Exception {
		
		
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost("192.168.17.17");
		connectionFactory.setPort(5672);
		connectionFactory.setVirtualHost("/");
		
		Connection connection = connectionFactory.newConnection();
		Channel channel = connection.createChannel();
		
		// 这就是一个普通的交换机 和 队列 以及路由
		String exchangeName = "test_dlx_exchange";
		String routingKey = "dlx.#";
		String queueName = "test_dlx_queue";
		
		channel.exchangeDeclare(exchangeName, "topic", true, false, null);
		
		Map<String, Object> agruments = new HashMap<String, Object>();
		agruments.put("x-dead-letter-exchange", "dlx.exchange");
		//这个agruments属性,要设置到声明队列上
		channel.queueDeclare(queueName, true, false, false, agruments);
		channel.queueBind(queueName, exchangeName, routingKey);
		
		//要进行死信队列的声明:
		channel.exchangeDeclare("dlx.exchange", "topic", true, false, null);
		channel.queueDeclare("dlx.queue", true, false, false, null);
		channel.queueBind("dlx.queue", "dlx.exchange", "#");
		//#
		
		channel.basicConsume(queueName, true, new MyConsumer(channel));
		
		
	}
}

猜你喜欢

转载自blog.csdn.net/lql_h/article/details/88813499
今日推荐