RabbitMQ-消息持久化和ACK演示

一)演示消息丢失现象

服务消费端

@Component
@RabbitListener(
        bindings = @QueueBinding(
                value = @Queue(value = "${spring.rabbitmq.queue.error.name}", autoDelete = "true"),
                exchange = @Exchange(value = "${spring.rabbitmq.exchange.name}", type = ExchangeTypes.DIRECT),
                key = "${spring.rabbitmq.queue.error.key}"
        )
)
public class ErrorQueue {


    @RabbitHandler
    public void info(String msg) {
        System.out.println("error......" + msg);
    }
}

服务提供端

@Component
public class Send {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 设置交换器的名称
     */
    @Value(value = "${spring.rabbitmq.exchange.name}")
    private String exchange;

    /**
     * 设置发送的key
     */
    @Value(value = "${spring.rabbitmq.queue.error.key}")
    private String key;

    public  void send(String msg){
  
        this.rabbitTemplate.convertAndSend(exchange,key,msg);
    }
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTests
{
    @Autowired
    private Send send;

    @Test
    public void contextLoads() throws InterruptedException
    {
        int flag = 0;//标记
        while (true)
        {
            flag++;
            Thread.sleep(2000);
            this.send.send("info"+flag);
        }
    }
}

演示消息丢失

1.消息正常发送

在这里插入图片描述
服务正在被消费

在这里插入图片描述

此时我们停止服务消费端让,服务生产端继续运行
消息的消费从62开始了,中间的产生的消息不见了,这就是消息丢失,

在这里插入图片描述

autoDelete 属性

解决出现的消息的问题

@Queue: 当所有消费客户端连接断开后,是否自动删除 队列 true:删除 false:不删除
@Exchange:当所有绑定队列都不在使用时,是否自动 删除交换器 true:删除 false:不删除

意思就是通过autoDelete属性保持队列的状态,就算出服务消费端宕机的情况,让队列依然存在,只是的有对应的服务进行消费而已,RabbitMQ会将没有消费的请求保存在对类中,一旦服务重启服务将继续消费

在这里插入图片描述

测试

通过管理界面已经有队在运行了

在这里插入图片描述

在服务消费到26的时候停掉服务消费端
在这里插入图片描述

在看管理界面,队列并没有消失,而且没有被处理的消息缓存在队列中
在这里插入图片描述

从新开启消费服务,接着停止的位置继续消费

在这里插入图片描述

以上就是RabbitMQ的消息持久化操作和相关的设置

二)RabbitMQ - ACK

在这里插入图片描述

演示ACK反馈的问题

借助上面的项目进行演示
1.在服务消费方添加一个的异常的抛出,让服务消费方无法正常的进行服务的消费

@Component
@RabbitListener(
        bindings = @QueueBinding(
                value = @Queue(value = "${spring.rabbitmq.queue.error.name}", autoDelete = "false"),
                exchange = @Exchange(value = "${spring.rabbitmq.exchange.name}", type = ExchangeTypes.DIRECT),
                key = "${spring.rabbitmq.queue.error.key}"
        )
)
public class ErrorQueue {


    @RabbitHandler
    public void info(String msg) {
        System.out.println("error......" + msg);
        throw  new RuntimeException();//抛出一个的异常
    }
}

2.测试代码

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTests
{
    @Autowired
    private Send send;

    @Test
    public void contextLoads() throws InterruptedException
    {
            Thread.sleep(2000);
            this.send.send("info");
    }
}

3.结果
我们发现服务端在一直对请求进行处理,这就是因为ACK返回的原因,如果请求被处理完毕消费端会反馈给的RabbtiMQ,告诉它这个消息已经被消费过了,而此时在方法执行中出现异常,此时的消息并没有反馈,导致的RabbitMQ不知道此消息是否完成了消费,会在此将此消息放入队列交给消费端进行消费,如此反复进如了死循环。
在这里插入图片描述

解决办法一:

加上try-catch语句块

   try
        {
            System.out.println("error......" + msg);
            throw  new RuntimeException();
        }catch (Exception e){
            
        }
    

解决办法二:

在全局配置文件内配置重复请求的次数

#开启重试
spring.rabbitmq.listener.simple.retry.enabled=true

#设置重复次数 默认是3次
spring.rabbitmq.listener.simple.retry.max-attempts=5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值