广告
返回顶部
首页 > 资讯 > 精选 >java中RabbitMQ高级应用方法
  • 556
分享到

java中RabbitMQ高级应用方法

2023-06-30 12:06:23 556人浏览 泡泡鱼
摘要

这篇文章主要介绍了java中RabbitMQ高级应用方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java中RabbitMQ高级应用方法文章都会有所收获,下面我们一起来看看吧。1、消息可靠性投递&e

这篇文章主要介绍了java中RabbitMQ高级应用方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java中RabbitMQ高级应用方法文章都会有所收获,下面我们一起来看看吧。

1、消息可靠性投递

 在使用 RabbitMQ 的时候,生产者在进行消息投递的时候如果想知道消息是否成功的投递到对应的交换机和队列中,有两种方式可以用来控制消息投递的可靠性模式 。

java中RabbitMQ高级应用方法

 由上图的整个消息的投递过程来看,生产者的消息进入到中间件中会首先到达交换机,然后再从交换机传递到队列中去,也就是分为两步走战略。那么消息的丢失情况也就是会出现在这两个阶段中,RabbitMQ 贴心的为我们提供了针对于这两个部分的可靠新传递模式:

  • confirm 模式

  • return 模式

 利用这两个回调模式来确保消息的传递可靠。

 1.1、确认模式

 消息从生产者到交换机之间传递会返回一个 confirmCallback 的回调。可以直接在 rabbitTemplate 实例中进行确认逻辑的设置。如果是使用 XML 配置的话需要在工厂配置开启 publisher-confirms="true"YAML 的配置就直接 publisher-confirm-type: correlated,他默认是 NONE ,需要手动开启。

@RunWith(springJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:spring-rabbitmq.xml")public class Producer {    @Autowired    private RabbitTemplate rabbitTemplate;    @Test    public void producer() throws InterruptedException {        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {            @Override            public void confirm(CorrelationData correlationData, boolean b, String s) {                System.out.println();                if (!b) {                    //消息重发之类的处理                    System.out.println(s);                } else {                    System.out.println("交换机成功接收消息");                }            }        });        rabbitTemplate.convertAndSend("default_exchange", "default_queue",                "hello world & beordie");        TimeUnit.SECONDS.sleep(5);    }}

 上面的确认是由一个 confirm 的函数执行的,里面携带了三个参数,第一个是配置的相关信息,第二个表示交换机是否成功的接收到消息,第三个参数是指没有成功接收消息的原因。

 1.2、退回模式

 从交换机到消息队列投递失败会返回一个 returnCallback 。在工厂配置中开启回退模式 publisher-returns="true" ,设置交换机处理消息失败的模式(默认 false 直接将消息进行丢弃),添加退回处理的逻辑。

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:spring-rabbitmq.xml")public class Producer {    @Autowired    private RabbitTemplate rabbitTemplate;    @Test    public void producer() throws InterruptedException {        rabbitTemplate.setMandatory(true);        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {            @Override            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {                //  重发逻辑处理                System.out.println(message.getBody() + " 投递消息队列失败");            }        });        rabbitTemplate.convertAndSend("default_exchange", "default_queue",                "hello world & beordie");        TimeUnit.SECONDS.sleep(5);    }}

 returnedMessage 中携带五个参数、分别指的是消息对象、错误码、错误信息、交换机、路由键。

 1.3、确认机制

 在消费者抓取消息队列中的数据取消费之后会有一个确认机制进行消息的确认,防止因为抓取消息之后但没有消费成功而导致的消息丢失。有三种确认方式:

  • 自动确认acknowledge="none"

  • 手动确认acknowledge="manual"

  • 根据异常情况确认acknowledge="auto"

 其中自动确认是指一旦消息被消费者抓取就自动默认成功,并将消息从消息队列中进行移除,如果这个时候消费端消费出现问题,那么也会是默认消息消费成功,但是实际上是没有消费成功的,也就是当前的消息丢失了。默认的情况就是自动确认机制。

 如果设置手动确认的方式,就需要在正常消费消息之后进行回调确认 channel.basicAck(),手动签收。如果业务处理过程中发生了异常则调用 channel.basicNack() 重新发送消息。

 首先需要在队列绑定时进行确认机制的配置,设置为手动签收。

<!-- 绑定队列 --><rabbit:listener-container connection-factory="rabbitFactory" auto-declare="true" acknowledge="manual">    <rabbit:listener ref="rabbirConsumer" queue-names="default_queue"/></rabbit:listener-container>

&emsp;生产者一端不用更改,只需要改变消费者的实现进行消息自动签收就可以了,正常执行业务则签收消息,业务发生错误则选择消息拒签,消息重发或者丢弃。

public class ConsumerAck implements ChannelAwareMessageListener {    @Override    public void onMessage(Message message, Channel channel) throws Exception {        //  消息唯一ID        long tag = message.getMessageProperties().getDeliveryTag();        try {            String msg = new String(message.getBody(), "utf-8");            channel.basicAck(tag, true);            System.out.println("接收消息: " + msg);        } catch (Exception e) {            System.out.println("接收消息异常");            channel.basicNack(tag, true, true);            e.printStackTrace();        }    }}

&emsp;里面涉及三个简单的签收函数,一是正确签收的 basicAck ,二是单条拒签的 basicReject ,三是批量拒签的 basicNack

  • basicAck 第一个参数表示消息在通道中的唯一ID,只针对当前的 Channel;第二个参数表示是否批量同意,如果是 false 的话只会同意签收当前ID的一条消息,将其从消息队列中进行删除,而如果是 true 的话将会把此ID之前的消息一起给同意签收了。

  • basicReject 第一个参数依旧表示消息的唯一ID,第二个参数表示是否重新回队发送,false 表示直接丢弃该条消息或者有死信队列可以接收, true 则表示重新回队进行消息发送,所有操作只针对当前的消息。

  • basicNack 比第二个多了一个参数,也就是处于中间位置的布尔值,表示是否批量进行。

2、消费端限流

&emsp;在用户请求和DB服务处理之间增加消息中间件的隔离,使得突发流量全部让消息队列来抗,降低服务端被冲垮的可能性。让所有的请求都往队列中存,消费端只需要匀速的取出消息进行消费,这样就能保证运行效率,也不会因为后台的阻塞而导致客户端得不到正常的响应(当然指的是一些不需要同步回显的任务)。

java中RabbitMQ高级应用方法

&emsp;只需要在消费者绑定消息队列时指定取出消息的速率即可,需要使用手动签收的方式,每进行一次的签收才会从队列中再取出下一条数据。

<!-- 绑定队列 --><rabbit:listener-container connection-factory="rabbitFactory" auto-declare="true"                           acknowledge="manual" prefetch="1">    <rabbit:listener ref="rabbirConsumer" queue-names="default_queue"/></rabbit:listener-container>

3、消息过期时间

&emsp;消息队列提供了存储在队列中消息的过期时间,分为两个方向的实现,一个是针对于整个队列中的所有消息,也就是队列的过期时间,另一个是针对当前消息的过期时间,也就是针对于单条消息单独设置。

&emsp;队列的过期时间设置很简单,只需要在创建队列时进行过期时间的指定即可,也可以通过控制台直接创建指定过期时间。一旦队列过期时间到了,队列中还未被消费的消息都将过期,进行队列的过期处理。

<rabbit:queue id="default_queue" name="default_queue" auto-declare="true">    <rabbit:queue-arguments>        <entry key="x-message-ttl" value="10000" value-type="java.lang.Integer"/>    </rabbit:queue-arguments></rabbit:queue>

&emsp;单条消息的过期时间需要在发送的时候进行单独的指定,发送的时候指定配置的额外信息,配置的编写由配置类完成。

&emsp;如果一条消息的过期时间到了,但是他此时处于队列的中间,那么他将不会被处理,只有当之后处理到时候才会进行判断是否过期。

MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {    @Override    public Message postProceSSMessage(Message message) throws        AmqpException {        //设置 message 的过期时间        message.getMessageProperties().setExpiration("5000");        //返回该消息        return message;    }};rabbitTemplate.convertAndSend("exchange", "route", "msg", messagePostProcessor);

&emsp;如果说同时设置了消息的过期时间和队列的过期时间,那么最终的过期时间由最短的时间进行决定,也就是说如果当前消息的过期时间没到,但是整个队列的过期时间到了,那么队列中的所有消息也自然就过期了,执行过期的处理策略。

4、死信队列

 4.1、死信概念

死信队列指的是死信交换机,当一条消息成为死信之后可以重新发送到另一个交换机进行处理,而进行处理的这个交换机就叫做死信交换机。

java中RabbitMQ高级应用方法

  • 消息成为死信消息有几种情况

    队列的消息长度达到限制

    消费者拒接消息的时候不把消息重新放入队列中

    队列存在消息过期设置,消息超时未被消费

    消息存在过期时间,在投递给消费者时发现过期

&emsp;在创建队列时可以在配置中指定相关的信息,例如死信交换机、队列长度等等,之后的一系列工作就不由程序员进行操作了,MQ 会自己完成配置过的事件响应。

<rabbit:queue id="default_queue" name="default_queue" auto-declare="true">    <rabbit:queue-arguments>        <!-- 死信交换机 -->        <entry key="x-dead-letter-exchange" value-type="dlx_exchane"/>        <!-- 路由 -->        <entry key="x-dead-letter-routing-key" value-type="dlx_routing"/>        <!-- 队列过期时间 -->        <entry key="x-message-ttl" value="10000" value-type="java.lang.Integer"/>        <!-- 队列长度 -->        <entry key="x-max-length" value-type="java.lang.Integer" value="10"/>    </rabbit:queue-arguments></rabbit:queue>

 4.2、延迟队列

&emsp;延迟队列指的是消息在进入队列后不会立即被消费,只有到达指定时间之后才会被消费,也就是需要有一个时间的判断条件。

&emsp;消息队列实际上是没有提供对延迟队列的实现的,但是可以通过 TTL + 死信队列 的方式完成,设置一个队列,不被任何的消费者所消费,所有的消息进入都会被保存在里面,设置队列的过期时间,一旦队列过期将所有的消息过渡到绑定的死信队列中。

&emsp;再由具体的消费者来消费死信队列中的消息,这样就实现了延迟队列的功能。

&emsp;例如实现一个下单超时支付取消订单的功能:

java中RabbitMQ高级应用方法

关于“java中RabbitMQ高级应用方法”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“java中RabbitMQ高级应用方法”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

--结束END--

本文标题: java中RabbitMQ高级应用方法

本文链接: https://www.lsjlt.com/news/328592.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • java中RabbitMQ高级应用方法
    这篇文章主要介绍了java中RabbitMQ高级应用方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java中RabbitMQ高级应用方法文章都会有所收获,下面我们一起来看看吧。1、消息可靠性投递&e...
    99+
    2023-06-30
  • java中RabbitMQ高级应用
    目录1、消息可靠性投递 1.1、确认模式 1.2、退回模式 1.3、确认机制2、消费端限流3、消息过期时间4、死信队列 4.1、死信概念&nb...
    99+
    2022-11-13
  • Java高级之HashMap中的entrySet()方法使用
    目录基本使用原理剖析总结基本使用 entrySet()方法得到HashMap中各个键值对映射关系的集合。 然后Map.Entry中包含了getKey()和getValue()方法获取...
    99+
    2023-03-22
    Java HashMap Java entrySet()方法 Java HashMap entrySet()方法
  • Java中ModelMapper的高级使用方法有哪些
    本篇内容介绍了“Java中ModelMapper的高级使用方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!ModelMapper 高...
    99+
    2023-06-29
  • Css的高级应用方法有哪些
    这篇文章主要介绍“Css的高级应用方法有哪些”,在日常操作中,相信很多人在Css的高级应用方法有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Css的高级应用方法有哪些”...
    99+
    2022-10-19
  • Java高级之HashMap中的entrySet()方法怎么使用
    本篇内容主要讲解“Java高级之HashMap中的entrySet()方法怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java高级之HashMap中的entrySet()方法怎么使用”...
    99+
    2023-07-05
  • Mybatis基础概念与高级应用方法
    今天小编给大家分享一下Mybatis基础概念与高级应用方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Mybatis基础回...
    99+
    2023-07-02
  • java高级用法之JNA中的Structure
    目录简介native中的structStructure特殊类型的Structure结构体数组作为参数结构体数组作为返回值结构体中的结构体结构体中的数组结构体中的可变字段结构体中的只读...
    99+
    2022-11-13
  • java高级用法之JNA中的Function
    目录简介function的定义Function的实际应用总结简介 在JNA中,为了和native的function进行映射,我们可以有两种mapping方式,第一种是interfac...
    99+
    2022-11-13
  • Java SpringBoot高级用法详解
    目录1,IDEA中Lombok作用创建项目2.pom.xml说明2.1 pom.xml标签说明2.2 依赖的相关说明2.3 SHA1介绍SpringBoot高级用法YML文件说明3....
    99+
    2022-11-12
  • VUE中常用的4种高级方法
    目录1. provide/inject2. 自定义v-model3. 事件总线(EventBus)3.1 创建一个全局Vue实例作为事件总线:3.2 在需要发送事件的组件中,使用$e...
    99+
    2023-05-19
    vue常用方法 vue高级方法
  • Laravel中where的高级使用方法
    这篇文章主要介绍了Laravel中where的高级使用方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。有时候项目中需要进行多个字段搜索就可以用到此方法在Larav...
    99+
    2023-06-08
  • OpenTelemetry Java SDK 高级用法解析
    目录引言启动命令引入依赖创建 sdk链路(Trace)创建 Tracer创建 Span获取当前 Span 对象创建 Attribute创建 Link Span创建 Event创建一个...
    99+
    2023-02-15
    OpenTelemetry Java SDK OpenTelemetry SDK高级用法
  • java枚举高级用法有哪些
    Java枚举的高级用法包括:1. 枚举的自定义方法:可以为枚举类型添加自定义方法,使其具有更多的功能。2. 枚举的构造函数和属性:可...
    99+
    2023-08-21
    java
  • java高级用法之JNA中的回调问题
    目录简介JNA中的Callbackcallback的应用callback的定义callback的获取和应用在多线程环境中使用callback总结简介 什么是callback呢?简单点...
    99+
    2022-11-13
  • java高级用法之JNA中使用类型映射
    目录简介类型映射的本质TypeMapperNativeMapped总结简介 JNA中有很多种映射,library的映射,函数的映射还有函数参数和返回值的映射,libary和函数的映射...
    99+
    2022-11-13
  • Java高级应用之斗地主游戏
    斗地主综合案例,供大家参考,具体内容如下 运用HashMap、ArrayList、List类实现斗地主综合案例,模拟斗地主游戏的随机发牌,并按照牌的大小和花色进行排列。 斗地主玩...
    99+
    2022-11-12
  • js中eval方法详解之eval方法的初级应用
    目录前言eval()方法的参数形式eval()方法的错误处理机制注意:总结前言 在我看来,js中的eval()方法就是一个js语言的执行器,它能把其中的参数按照JavaScript语...
    99+
    2023-01-16
    js的eval方法 js eval()函数的作用是什么 javascript中eval函数
  • Java中ModelMapper 的高级使用
    目录ModelMapper高级使用使用实例实体类ModelMapper配置类ModelMapperService类测试类测试结果ModelMapper 高级使用  &ems...
    99+
    2022-11-13
  • VUE中常用的四种高级方法总结
    目录1. provide/inject2. 自定义v-model3. 事件总线(EventBus)3.1 创建一个全局Vue实例作为事件总线:3.2 在需要发送事件的组件中,使用$e...
    99+
    2023-05-18
    vue 高级用法 vue高级技巧 vue常用的方法有哪些
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作