RabbitMQ的高级属性详解

rabbitMQ的高级属性详解

一:消费端消费消息是同步的还是异步的

同步消费(单线程消费),在实际开发中,为了提高消费端的消费效率,会在消费端使用线程池并发消费

1. 服务端

public class Provider {
    public static void main ( String[] args ) throws IOException {
//        获取连接
        Connection connection = ConnectionUtils.getConnection();
//        创建通道
        Channel channel = connection.createChannel();
//        声明队列
        channel.queueDeclare("queueH",false,false,false,null);
//        发送消息到队列
//        String exchange, String routingKey, BasicProperties props, byte[] body)
        for (int i = 0; i < 100; i++) {
            channel.basicPublish("","queueH",null,("hellow"+i).getBytes());

        }

//        关闭连接 连接关闭以后通道会自动关闭
        connection.close();
    }
}

2. 消费端

public class Consumer {

    public static void main ( String[] args ) throws IOException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
//        获取连接
        Connection connection = ConnectionUtils.getConnection();
//        创建通道
        Channel channel = connection.createChannel();
//        声明队列
        channel.queueDeclare("queueH",false,false,false,null);
//        消费消息
        channel.basicConsume("queueH",new DefaultConsumer(channel){
            @Override
            public void handleDelivery ( String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body ) throws IOException {
//                System.out.println(envelope.getDeliveryTag());
                executorService.submit(new Runnable() {
                    @Override
                    public void run () {
                        System.out.println(new String(body));
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });

            }
        });
    }
}

二:消息的过期时间-TTL

2.1 通过队列的方式,设置消息的过期时间(对队列中的所有消息有效)

  HashMap<String, Object> map = new HashMap<>();
        map.put("x-message-ttl",5000);
//        声明队列
   channel.queueDeclare("queueH",false,false,false,map);

2.2 给消息本身设置过期时间

//        声明队列
        channel.queueDeclare("queueH",false,false,false,null);
//        发送消息到队列
//        给消息本身设置过期时间
        AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().expiration("5000").build();
        for (int i = 0; i < 100; i++) {
            channel.basicPublish("","queueH",properties,("hellow"+i).getBytes());

        }

2.3 队列的过期时间

 HashMap<String, Object> map = new HashMap<>();
//        设置过期时间后,到期后,队列会自动删除
  map.put("x-expires",5000);
//        声明队列
 channel.queueDeclare("queueH01",false,false,false,map);

三: 设置消息的优先级

注意:优先级队列,必须在消息堆积时才有意义,如果消费速度>消息的发布速度,优先级队列是没有任何作用的
public class Provider {
    public static void main ( String[] args ) throws IOException {
//        获取连接
        Connection connection = ConnectionUtils.getConnection();
//        创建通道
        Channel channel = connection.createChannel();
        HashMap<String, Object> map = new HashMap<>();
//        设置队列的最大优先级,这个队列的最大优先级是100
        map.put("x-max-priority",100);
//        声明队列
        channel.queueDeclare("queueH",false,false,false,map);
//        发送消息到队列
        for (int i = 0; i < 100; i++) {
            //        设置1-100的随机数
            int random = (int) (Math.random()*100+1);
//             ,设置消息的优先级
            AMQP.BasicProperties properties = new AMQP.BasicProperties().builder()
                    .priority(random)
                    .build();
            channel.basicPublish("","queueH",properties,("hellow"+random).getBytes());
        }

//        关闭连接 连接关闭以后通道会自动关闭
        connection.close();
    }
}

四:死信队列

什么是死信队列

死信消息:一个普通队列中,如果发生了消息过期的问题(也有可能是其他问题),那么这个消息就会被丢弃,被丢弃的消息就称之为死信消息

死信路由:一个普通的队列,如果绑定了死信路由,则所有的死信消息不会直接被丢弃,而是转发给死信路由

死信队列:和死信路由绑定在一起的队列就称之为死信队列

public class Provider {
    public static void main ( String[] args ) throws IOException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
//        声明一个死信队列,以及一个死信路由,并让死信队列绑定死信路由
        channel.queueDeclare("dead",false,false,false,null);
        channel.exchangeDeclare("deadroute","fanout");
        channel.queueBind("dead","deadroute","");
//        声明一个正常的队列,这个队列设置死信属性
        HashMap<String, Object> map = new HashMap<>();
//        给队列中的所有消息设置一个过期时间,消息到期后,就会变成死信消息
        map.put("x-message-ttl",7000);
        map.put("x-dead-letter-exchange","deadroute");
        channel.queueDeclare("normal",false,false,false,map);
//        发送消息
        channel.basicPublish("","normal",null,"xiaoxi".getBytes());
    }
}

五:延迟队列

实现:通过TTL+死信队列来实现

代码与模拟的死信队列的代码相同

六:消息的持久化

什么是消息的持久化

消息的持久化也就是说当rabbitmq服务关闭以后,消息不丢失,默认rabbitmq的消息是非持久化的

注意:

1.队列的持久化不意为着消息的持久化

2.队列如果不设置持久化,消息持久化毫无意义

3.消息持久化其实就是将消息写入硬盘,如果所有消息都持久化,必然会降低RabbitMq服务的消息吞吐量,所以实际开发过程中,尽量只让需要的消息持久化

//设置消息的持久化
AMQP.BasicProperties properties = new AMQP.BasicProperties()
        .builder()
        .deliveryMode(2)//消息持久化模式
        .build();

//也可直接使用该常量
//MessageProperties.PERSISTENT_TEXT_PLAIN;
channel.basicPublish("normal-exchange", "", properties, msg.getBytes("utf-8"));

七: RabbitMQ的消息确认机制

1. 提供者的消息确认机制

1. 通过事务模式
public class Provider01 {
    public static void main ( String[] args ) throws IOException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("queue03",false,false,false,null);
//        通过事务模式实现消息确认机制
//            1. 开启事务
        channel.txSelect();
        try {
//            设置消息的持久化
            AMQP.BasicProperties properties = new AMQP.BasicProperties().builder()
                    .deliveryMode(2)
                    .build();
//            第二种消息持久化方式
//            AMQP.BasicProperties properties1 = MessageProperties.PERSISTENT_TEXT_PLAIN;
//            发送消息
//            如果消息发送成功,则提交事务
            channel.txCommit();
        }catch (Exception e){
//            出现异常,事务回滚
         channel.txRollback();
//         进行消息的重试与补偿
        }
    }
}
2.confirm的同步模式
public class Provider02 {
    public static void main ( String[] args ) throws IOException, InterruptedException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("queue03",false,false,false,null);
//    开启confirm机制
        channel.confirmSelect();
//        发送消息
//        这里是发送消息
//        同步等到rabbitmq的响应
        boolean b = channel.waitForConfirms();
        if (!b){
//            进行消息的重试和补偿机制
        }
    }
}
3.confirm的异步模式
public class Provider03 {
    public static void main ( String[] args ) throws IOException, InterruptedException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare("queue03", false, false, false, null);
//    开启confirm机制
        channel.confirmSelect();
//        发送消息
//        这里是发送消息
//        设置异步的监听方法
        channel.addConfirmListener(new ConfirmListener() {
            /**
             * 如果消息成功,就会回调该方法
             * @param deliveryTag 表示成功的消息id
             * @param multiple 表示是否批量,如果为true,就说明消息id之前的全部成功,如果为false。说明单个消息成功
             * @throws IOException
             */
            @Override
            public void handleAck ( long deliveryTag, boolean multiple ) throws IOException {

            }

            /**
             * 如果消息失败,就会回调该方法
             * @param deliveryTag 失败的消息id
             * @param multiple 表示是否批量失败,如果为true,批量失败,为false,单个失败
             * @throws IOException
             */

            @Override
            public void handleNack ( long deliveryTag, boolean multiple ) throws IOException {
                
            }
        });
    }

}

八:消息的手动签收和重回队列

在消费端进行手动签收和重回队列

public class Consumer {
    public static void main ( String[] args ) throws IOException {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
//        手动确认消息,第二个参数必须设置为fasle
        channel.basicConsume("queueH06",false,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);
//                消息的重回队列
//                第三个参数,表示是否重回队列,true,重回队列,fasle。变成死信消息
                channel.basicNack(envelope.getDeliveryTag(),false,true);
            }
        });

    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值