RabbitMQ拓展

|▌冷眼眸甩不掉的悲伤 提交于 2020-02-13 00:03:28

RabbitMQ拓展

TTL队列/消息

  1. TTL是Time To Live的缩写, 也就是生存时间
  2. RabbitMQ支持消息的过期时间, 在消息发送时可以进行指定
  3. RabbitMQ支持队列的过期时间, 从消息入队列开始计算, 只要超过了队列的超时时间配置, 那么消息会自动清除

生产者

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.victoria.rabbitmq.util.ConnectionUtils;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class send {
    private static final String EXCHANGE_NAME = "test_exchange_ttl";
    public static void main(String[] args) throws IOException, TimeoutException {
        //获取链接
        Connection connection = ConnectionUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //交换机声明
        channel.exchangeDeclare(EXCHANGE_NAME,"topic",true);
        //路由键
        String rount_key = "user.add";
        //发送消息
        for(int i = 0 ;i<5;i++){
            String msg_str = "Hello TTl msg"+i;
            channel.basicPublish(EXCHANGE_NAME,rount_key,null,msg_str.getBytes());
        }
        //关闭链接
        channel.close();
        connection.close();
    }
}

消费者

import com.rabbitmq.client.*;
import com.victoria.rabbitmq.util.ConnectionUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

public class recv {
    private static final String EXCHANGE_NAME = "test_exchange_ttl";
    private static final String QUEUE_NAME = "test_queue_ttl";
    public static void main(String[] args) throws IOException, TimeoutException {
        //获取链接
        Connection connection = ConnectionUtils.getConnection();
        //创建通道
        final Channel channel = connection.createChannel();
        //限流
        channel.basicQos(1);
        //配置参数
        Map<String,Object> map = new HashMap<String, Object>();
        //配置ttl过期时间
        map.put("x-message-ttl", 10000);
        //声明队列和交换机
        channel.queueDeclare(QUEUE_NAME,true,false,false,map);
        channel.exchangeDeclare(EXCHANGE_NAME,"topic",true);
        //路由键匹配
        String rount_key = "user.#";
        //队列绑定交换机
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,rount_key);
        //消费者
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(new String(body));
                //ack认证
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        //监听
        channel.basicConsume(QUEUE_NAME,false,consumer);
    }
}

DLX(死信队列)

  1. Dead-Letter-Exchange
  2. 利用DLX, 当消息在一个队列中变成死信(dead message)之后, 它能被重新publish到另一个Exchange, 这个Exchange就是DLX
  3. DLX也是一个正常的Exchange, 和一般的Exchange没有区别, 它能在任何队列上被指定, 实际上就是设置某个队列的属性为死信队列
  4. 当这个队列中有死信时, RabbitMQ就会自动将这个消息重新发布到设置的Exchange上去, 进而被路由到另一个队列
  5. 可以监听这个队列中消息做相应的处理, 这个特性可以弥补RabbitMQ3.0以前支持的immediate参数的功能

消息变成死信队列的几种情况

  1. 消息被拒绝(basic.reject/basic.nack) 并且requeue重回队列设置成false
  2. 消息TTL过期
  3. 队列达到最大长度

死信队列的配置

  1. 首先要设置死信队列的exchange和queue,然后进行绑定(死信队列的交换机名和队列名只能这样写)
    1.Exchange : dlx.exchange
    2.Queue : dlx.queue
    3.RoutingKey : #
  2. 然后正常声明交换机, 队列, 绑定, 只不过需要在队列加上一个扩展参数即可 : arguments.put(“x-dead-letter-exchange”, “dlx.exchange”);
  3. 这样消息在过期, reject或nack(requeue要设置成false), 队列在达到最大长度时, 消息就可以直接路由到死信队列

生产者

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.victoria.rabbitmq.util.ConnectionUtils;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class send {
    private static final String EXCHANGE_NAME = "test_exchange_dlx";
    public static void main(String[] args) throws IOException, TimeoutException {
        //获取链接
        Connection connection = ConnectionUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //路由键
        String rount_key = "user.add";
        //消息十秒没被消费则过期
        AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().expiration("10000").build();
        //生产者发送消息
        for(int i =0;i<5;i++){
            String str_msg = "hello dlx msg"+i;
            channel.basicPublish(EXCHANGE_NAME,rount_key,properties,str_msg.getBytes());
        }
        //关闭链接
        channel.close();
        connection.close();
    }
}

消费者

import com.rabbitmq.client.*;
import com.victoria.rabbitmq.util.ConnectionUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

public class recv {
    private static final String EXCHANGE_NAME = "test_exchange_dlx";
    private static final String QUEUE_NAME = "test_queue_dlx";
    //注意:死信队列的交换机名和队列名只能这样取
    private static final String EXCHANGE_DLX_NAME = "dlx.exchange";
    private static final String QUEUE_DLX_NAME = "dlx.queue";
    public static void main(String[] args) throws IOException, TimeoutException {
        //获取链接
        Connection connection = ConnectionUtils.getConnection();
        //创建通道
        final Channel channel = connection.createChannel();
        //限流
        channel.basicQos(1);
        //定义死信队列的队列和交换机
        channel.exchangeDeclare(EXCHANGE_DLX_NAME,"topic",true);
        channel.queueDeclare(QUEUE_DLX_NAME,true,false,false,null);
        //绑定
        channel.queueBind(QUEUE_DLX_NAME,EXCHANGE_DLX_NAME,"#");
        //定义交换机和队列
        channel.exchangeDeclare(EXCHANGE_NAME,"topic",true);
        //给与死信队列配置
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("x-dead-letter-exchange",EXCHANGE_DLX_NAME);
        channel.queueDeclare(QUEUE_NAME,true,false,false,map);
        //路由键
        String rount_key = "user.#";
        //绑定
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,rount_key);
        //消费者消费消息
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println(new String(body));
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        //监听
        channel.basicConsume(QUEUE_NAME,false,consumer);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!