springboot之rabbit - producer的confirm和consumer的ack模式

简介: 本篇和大家分享的是关于rabbit的生产和消费方的一些实用的操作;正如文章标题,主要内容如producer的confirm和consumer的ack,这两者使用的模式都是用来保证数据完整性,防止数据丢失。
+关注继续查看

本篇和大家分享的是关于rabbit的生产和消费方的一些实用的操作;正如文章标题,主要内容如producer的confirm和consumer的ack,这两者使用的模式都是用来保证数据完整性,防止数据丢失

  • producer的confirm模式
  • consumer的ack模式

producer的confirm模式

首先,有这样一种业务场景1:a系统在做活动前,需要给用户的手机发送一条活动内容短信希望用户来参加,因为用户量有点大,所以通过往短信mq中插入数据方式,让短信服务来消费mq发短信;
此时插入mq消息的服务为了保证给所有用户发消息,并且要在短时间内插入完成(因此用到了异步插入方式(快速)),我们就需要知道每次插入mq是否成功,如果不成功那我们可以收集失败的信息后补发(因此confirm模式排上了用场);如图设计:
image
在springboot中可以使用基于amqp封装的工厂类来开启confirm模式,然后通过RabbitTemplate模板来设置回调函数,如下代码:

    ///region producer生产 - confirm模式

    public RabbitTemplate getRabbitTemplate(RabbitTemplate.ConfirmCallback confirmCallback) {
        return this.getRabbitTemplate(this.connectionFactory(), confirmCallback);
    }

    public RabbitTemplate getRabbitTemplate(CachingConnectionFactory connectionFactory, RabbitTemplate.ConfirmCallback confirmCallback) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        //product开启confirm模式
        connectionFactory.setPublisherConfirms(true);
        //设置confirm回调处理
        template.setConfirmCallback(confirmCallback);
        return template;
    }
    ///endregion

这里通过RabbitTemplate.ConfirmCallback函数编程来传递我们自定义的回调方法,如下收集confirm返回的结果信息:

        RabbitUtil rabbitUtil = new RabbitUtil(this.getFirstNode().getLink());
        RabbitTemplate template = rabbitUtil.getRabbitTemplate((a, b, c) -> {
            System.out.println("firstNodeTpl - ConfirmCallback的Id:" + a.getId() + ";状态:" + b + ";信息:" + c);
        });

最后再通过RabbitTemplate实例的convertAndSend方法发送mq信息,我们能够在日志中看到如下记录的信息:
image
这里的状态true:表示send成功,false:表示send失败;通常false的时候信息c会有响应的错误提示,这里把网络断开,如下错误提示:
image

consumer的ack模式

再来,有这样一种场景2:短信服务去消费mq队列信息时,倘若服务调用的运营商发送短信接口异常了(短信运营商接口欠费),我们此时的短信是发送失败的,用户也收不到短信,但是在默认(默认开启ack)前提下mq消息已经被消费了rabbit中没有记录了(kafka例外);想要mq消息在业务逻辑异常时还存在,那么可以使用ack方式;

image
在springboot中可以使用基于amqp封装的工厂类关闭自动ack模式,改为手动ack方式;只有当业务代码流程走完后,最后通过代码设置ack标识,来通知rabbit消息可以丢弃了;如果设置了手动模式后,又没有提交ack标识,那么mq中的消息一直存在无法释放(每次consumer消费后,rabbit会把noack的消息重复放入队列中):

    ///region consumer监听 - 手动ack
    public SimpleRabbitListenerContainerFactory listenerContainerFactory() {
        return this.listenerContainerFactory(this.connectionFactory());
    }

    public SimpleRabbitListenerContainerFactory listenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        //代码手动ack
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        //开启消费者数量
        factory.setConcurrentConsumers(2);
        //每次接受数据量,默认250
        factory.setPrefetchCount(300);
        return factory;
    }
    ///endregion

通过连接工厂设置手动ack方式,然后获取mq消息后,走完正常业务逻辑,最后再手动通知ack释放消息,如下:

    @RabbitListener(containerFactory = "firstNodeListener", queues = {"${shenniu.rabbits.firstNode.queue}"})
    private void firstNodeListener(String msg, Channel channel, Message message) {
        try {
            long deliverTag = message.getMessageProperties().getDeliveryTag();
            System.out.println("firstNodeListener - 消费消息 [" + deliverTag + "] - " + msg);
            channel.basicAck(deliverTag, true);
        } catch (Exception ex) {
        }
    }

这里ack主要根据mq消息的唯一编号(deliverTag)来通知;如果我们不设置ack确认,那么消息状态会是这样如下rabbit管理后台:
image

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
3月前
|
安全 Java Spring
SpringBoot整合Spring Security,使用formLogin模式进行鉴权(二)
在configure(HttpSecurity http)方法里写入如下代码
29 0
|
3月前
|
设计模式 消息中间件 Java
SpringBoot事件监听机制及观察者/发布订阅模式详解
介绍观察者模式和发布订阅模式的区别。 SpringBoot快速入门事件监听。 什么是观察者模式? 观察者模式是经典行为型设计模式之一。 在GoF的《设计模式》中,观察者模式的定义:在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。如果你觉得比较抽象,接下来这个例子应该会让你有所感觉:
|
3月前
|
消息中间件 设计模式 Java
SpringBoot事件监听机制及观察者模式/发布订阅模式
SpringBoot事件监听机制及观察者模式/发布订阅模式
149 0
|
4月前
|
消息中间件 Java Spring
SpringBoot RabbitMq 六大模式
依赖、配置 依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
44 1
|
5月前
JAVA+SpringBoot框架+SaaS模式云HIS源码
云HIS融合B/S版电子病历系统,支持电子病历四级,HIS与电子病历系统均拥有自主知识产权。
104 0
|
7月前
|
网络协议 Java 应用服务中间件
SpringBoot中支持的Web服务器,网络模式和网络协议
SpringBoot中支持的Web服务器,网络模式和网络协议
174 0
SpringBoot中支持的Web服务器,网络模式和网络协议
|
9月前
|
消息中间件 Java Spring
RabbitMQ:第三章:Springboot集成RabbitMQ(直连模式,工作队列模式,发布订阅模式,路由模式,通配符模式)
RabbitMQ:第三章:Springboot集成RabbitMQ(直连模式,工作队列模式,发布订阅模式,路由模式,通配符模式)
210 0
RabbitMQ:第三章:Springboot集成RabbitMQ(直连模式,工作队列模式,发布订阅模式,路由模式,通配符模式)
|
10月前
|
消息中间件 Java
SpringBoot整合ActiveMq实现Queue和Topic两种模式
SpringBoot整合ActiveMq实现Queue和Topic两种模式
SpringBoot整合ActiveMq实现Queue和Topic两种模式
|
11月前
|
NoSQL Java Redis
SpringBoot整合Jedis可切换使用单机、哨兵、集群模式
SpringBoot整合Jedis可利用配置文件一键切换使用单机、哨兵、集群模式
368 0
|
消息中间件 缓存 监控
RabbitMQ 进阶 -- SpringBoot 集成 RabbitMQ实现生产者与消费者模式
Spring Boot 如何集成RabbitMQ ,详解Spring Boot集成RabbitMQ!
657 0
RabbitMQ 进阶 -- SpringBoot 集成 RabbitMQ实现生产者与消费者模式
推荐文章
更多