rabbitmq-消息时效与死信队列

TTL:

当我们的信息过多时会导致队列(queue)内存耗尽无法正常接收信息的情况,此时我们可以对部分非重要的信息设置时效性,超过指定时间还未被处理则queue自动丢弃该条消息,以确保queue内存不被占满。

/**
 * Created by py
 */
public class TTLProcuder {
    private static final String queue = "simple_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection instance = RabbitUtils.getInstance();
        Channel channel = instance.createChannel();
        Map<String,Object> headers = new HashMap<>();
        headers.put("h1","123");
        headers.put("h2","456");
        /**
         * deliveryMode:2 表示消息持久化
         * contentEncoding:该信息的传输格式
         * headers:自定义的传输参数
         * expiration:失效时间 毫秒
         */
        AMQP.BasicProperties build = new AMQP.BasicProperties.Builder()
                .deliveryMode(2).contentEncoding("utf-8")
                .expiration("10000").headers(headers).build();
        for (int i = 0; i <5 ; i++) {
            String msg = "this is a message:"+i;
            /**
             * queue:在rabbit中已存在不需要再次声明
             * false:未找到指定队列就丢弃该条消息
             * build:对该条消息的自定义配置
             * todo 使用该种方式是针对当前发送的这条消息所做的配置,不是针对该队列所做的配置
             */
            channel.basicPublish("",queue,false,build,msg.getBytes());
        }
        System.out.println("消息发送完成");
        channel.close();
        instance.close();
    }
}

上述代码实现我们指定某一条消息的时效时长,现在我们设置队列中所有的消息都在指定时间后失效。

/**
 * Created by py
 * 2020/5/2
 */
public class TTLProcuder {

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection instance = RabbitUtils.getInstance();
        Channel channel = instance.createChannel();
        //该设置让ttl-queue的所有消息都是20S后自动丢失
        Map<String,Object> arguments = new HashMap<>();
        arguments.put("x-message-ttl",20000);
        channel.queueDeclare("ttl-queue",true,false,false,arguments);
        for (int i = 0; i <5 ; i++) {
            String msg = "this is a message:"+i;
            channel.basicPublish("","ttl-queue",false,null,msg.getBytes());
        }
        System.out.println("消息发送完成");
        channel.close();
        instance.close();
    }
}

死信队列:

上述说明为防止queue的信息堆积过多导致无法接收信息时可以通过设置信息时效来控制,如果我们不想将这部分的信息完全丢弃我们可以通过配置死信队列来处理。

消息在queueA中超过10s未被消费,按照设置应该自动删除(消息只保留10S),此时通过配置死信队列可实现将该条信息从queueA中移动到死信队列中来,这样既释放了queueA的内存空间又保留了该条信息。

简示图:

代码:

import com.example.springcloud.eurekaclinet1demo.uitl.RabbitUtils;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 生产者
 * Created by py
 */
public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection instance = RabbitUtils.getInstance();
        Channel channel = instance.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, true, properties, msg.getBytes());
        }
        System.out.println("消息发送完成");
        channel.close();
        instance.close();
    }
}
/**
 * 消费者
 * Created by py
 */
public class Consumer {

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection instance = RabbitUtils.getInstance();
        Channel channel = instance.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", "#");
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                System.err.println("-----------consume message----------");
                System.err.println("consumerTag: " + consumerTag);
                System.err.println("envelope: " + envelope);
                System.err.println("properties: " + properties);
                System.err.println("body: " + new String(body));
                //消费者接收到消息,但是没有正常处理,返回给rabbit。
                //配置死信队列后该条信息也会推送到私信队列中,而不会回到原有队列中
                /**
                 * public void basicNack(long deliveryTag, boolean multiple, boolean requeue)
                 * deliveryTag: 该条消息的标识
                 * multiple: 多条消息还是单条消息;false:单条消息
                 * requeue:该条消息是否重新返回队列;false:直接丢弃不返回
                 */
                //channel.basicNack(envelope.getDeliveryTag(),false,false);
            }
        };
        channel.basicConsume(queueName, false, defaultConsumer);
        System.out.println("消费者已启动");
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值