RabbitMQ使用二----进阶

本文详细讲解了如何在SpringBoot应用中使用RabbitMQ实现消息的可靠投递,包括确认模式、退回模式、持久化以及客户端确认。还介绍了消费端限流和设置TTL的功能,以及如何通过代码动态创建交换机和队列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、消息可靠性投递

消息传递过程中可能出现问题的节点:
	1、生产者到交换机
	2、交换机到队列
	3、在队列中丢失
	4、队列到消费者

解决方案:

1、 确认模式(confirm)

	该模式用于保证生产者到交换机这个阶段消息的安全性。之前案例中,生产者发送消息到交换机,也没有确认是否发送成功,发了就是发了,没有安全性。使用确认模
式,可以将在消息发送完,接收消息的发送状态,根据发送成功与否,再去进行下边的业务逻辑。

Ⅰ、在application.yml文件中开启手动确认模式

server:
  port: 8080
spring:
  rabbitmq:
    host: 192.168.253.128
#    开启rabbitMQ的生产方确认模式  生产者到交换机
    publisher-confirm-type: correlated

所有生产者代码都在测试类中写
Ⅱ、生产者代码:

	@SpringBootTest(classes = ProducerApp.class)中的ProducerApp是springboot的启动类的类名
@SpringBootTest(classes = ProducerApp.class)
public class DemoTest1 {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void confirmDemo(){

        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            //ack的值为true和false,成功为true
                System.out.println(ack);
            }
        });
        for(int i=0;i<10;i++) {
            rabbitTemplate.convertAndSend("fy_fanout", "", "hello super");
        }
    }
}

2、 退回模式(return)

退回模式解决了交换机和队列之间传递消息的安全性问题。交换机分发消息给队列,如果队列没有接收成功,则回退给交换机。根据返回的信息,进行下一步操作

Ⅰ、在application.yml文件中开启退回模式

server:
  port: 8080
spring:
  rabbitmq:
    host: 192.168.253.128
#    开启rabbitMQ的生产方确认模式  生产者到交换机
    publisher-confirm-type: correlated
#    开启发布者退回模式   交换机到队列
    publisher-returns: true

2、示例代码

@SpringBootTest(classes = ProducerApp.class)
public class DemoTest1 {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void returnDemo(){
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returned) {
                System.out.println("消息从交换机到队列发生错误"+returned.getReplyText());
            }
        });

//        可以让交换机和队列间的routing key 不匹配,来模拟分发消息失败
        rabbitTemplate.convertAndSend("fy_topic","pppppppppp","hello return");
    }

}

3、持久化

将队列数据持久化,防止队列数据丢失

4、客户端确认

	解决了队列到客户端之间数据的安全性问题。一般情况下,客户端在拿到消息后,不管业务是否执行成功,队列中的该条消息都会被删除,那么如果业务逻辑没有执行成
功,再次拿该条消息进行业务处理时,就发现消息不存在,这是有问题的。解决方法:当客户端的业务逻辑执行成功后,确认后,再让队列将消息删除。

Ⅰ、在消费端模块中的application.yml中开启手动确认模式

server:
  port: 8081
spring:
  rabbitmq:
    host: 192.168.253.128
    listener:
      simple:
#        消费端需要手动确认,有三个值 none 自动,manual 手动,auto 根据情况
        acknowledge-mode: manual

Ⅱ、消费端的实现

自己加一个出错信息,模拟业务逻辑出现问题,观察控制台打印结果以及队列中的数据变化
@Component
public class Listener01 {
    @RabbitListener(queues = "lyd_fanout01")
    public void listener(Message message, Channel channel) throws IOException {
//        消息的标识标签
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
//        队列中的信息
        byte[] body = message.getBody();
        String msg=new String(body);

        System.out.println(msg);

        try{
//            int a= 10 / 0;
            System.out.println("业务逻辑处理");
            /**
             * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver}
             * @param multiple true to reject all messages up to and including
             */
//            消费端手动确认消息
            channel.basicAck(deliveryTag,true); //确定接收后消息从队列中删除
        }catch (Exception e){
            /**
            
             * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver}
             * @param multiple true to reject all messages up to and including
             * the supplied delivery tag; false to reject just the supplied
             * delivery tag.
             * @param requeue true if the rejected message(s) should be requeued rather
             */
            channel.basicNack(deliveryTag,true,true);//如果业务出错,则消息不删除,并再次发从该消息
        }
    }

}

二、消费端限流

为什么要消费端限流:
	如果有大量的消息堆积在队列中,而消费端的业务逻辑耗时很长,就不能一下让太多的访问消息到达消费端,严重了就服务器挂掉。

Ⅰ、消费端模块application.yml中开启限流

server:
  port: 8081
spring:
  rabbitmq:
    host: 192.168.253.128
    listener:
      simple:
#        消费端需要手动确认
        acknowledge-mode: manual
#        每次拿三个消息
        prefetch: 3

Ⅱ、观看效果

使用上边客户端确认的代码,将channel.ack()方法注释了,不要有异常,就可以观看到效果

三、TTL(设置队列的存活时间)

1、设置的时间是给队列中的消息设置的。
2、如果消息没有在队头,那么即使存活时间到了,也不会被队列删除,但是这条消息是读取不到的

Ⅰ、给队列中的单个元素设置过期时间

@SpringBootTest(classes = ProducerApp.class)
public class DemoTest1 {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
//    给单个消息设置存活时间
    @Test
    public void infoTTL(){
        for(int i=0;i<10;i++){
//            i=3时,设置消息存活时间20秒
            if(i==3){
                MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        message.getMessageProperties().setExpiration("20000");
                        return message;
                    }
                };
                rabbitTemplate.convertAndSend("fy_fanout","","hello return"+i,messagePostProcessor);
            }else {
                rabbitTemplate.convertAndSend("fy_fanout","","hello return"+i);
            }
        }

    }
}

Ⅱ、使用浏览器端给整个队列设置时间,作用到的也是队列中的消息

在这里插入图片描述在创建队列时设置存活时间

四、springboot中使用代码创建交换机、队列

@Configuration
public class RabbitConfig {
    @Bean
    public Exchange exchange(){
//        创建交换机,并命名,设置持久性
        Exchange exchange = ExchangeBuilder.fanoutExchange("fy_fanout01").durable(true).build();
        return exchange;
    }

    @Bean
    public Queue queue(){
//        创建队列,并命名,设置队列中消息的存活时间
        Queue queue = QueueBuilder.durable("lyd_fanout04").withArgument("x-message-ttl",20000).build();
        return queue;
    }

    @Bean
    public Binding binding(Queue queue,Exchange exchange){
//        绑定交换机和队列
       return   BindingBuilder.bind(queue).to(exchange).with("").noargs();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值