我的编程空间,编程开发者的网络收藏夹
学习永远不晚

java中RabbitMQ高级应用方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

java中RabbitMQ高级应用方法

这篇文章主要介绍了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高级应用方法”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

java中RabbitMQ高级应用方法

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

下载Word文档

猜你喜欢

java中RabbitMQ高级应用方法

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

在 Java 中,unshift 方法的高级使用技巧有哪些?(java中unshift方法的高级用法)

在Java编程中,unshift方法是数组对象的一个重要方法,它用于在数组的开头添加一个或多个元素,并返回新数组的长度。虽然unshift方法在日常的数组操作中较为常见,但它还有一些高级用法,可以帮助我们更灵活地处理数组数据。
在 Java 中,unshift 方法的高级使用技巧有哪些?(java中unshift方法的高级用法)
Java2024-12-15

Java高级之HashMap中的entrySet()方法使用

这篇文章主要介绍了Java高级之HashMap中的entrySet()方法使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-22

Java中ModelMapper的高级使用方法有哪些

本篇内容介绍了“Java中ModelMapper的高级使用方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!ModelMapper 高
2023-06-29

Java中注解的高级用法

注解本身没有含义,主要作用是标记目标元素,后续拿到改标识的元数据,进行一系列的处理。注解的使用是非常广泛的,各种框架中都使用频繁,基于注解可以将很多抽象功能提取出来,通过简单 的标识来实现各种复杂的功能。

Java高级之HashMap中的entrySet()方法怎么使用

本篇内容主要讲解“Java高级之HashMap中的entrySet()方法怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java高级之HashMap中的entrySet()方法怎么使用”
2023-07-05

Mybatis基础概念与高级应用方法

今天小编给大家分享一下Mybatis基础概念与高级应用方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Mybatis基础回
2023-07-02

在 Java 中如何应用 string 的方法?(java中string的方法怎么应用)

在Java中,String是一个非常重要且常用的类,它提供了许多方便的方法来处理字符串。以下是关于Java中String方法应用的详细介绍。一、字符串的创建与初始化在
在 Java 中如何应用 string 的方法?(java中string的方法怎么应用)
Java2024-12-15

VUE中常用的4种高级方法

provide/inject是Vue.js中用于跨组件传递数据的一种高级技术,它可以将数据注入到一个组件中,然后让它的所有子孙组件都可以访问到这个数据,这篇文章主要介绍了VUE中常用的4种高级方法,需要的朋友可以参考下
2023-05-19

Laravel中where的高级使用方法

这篇文章主要介绍了Laravel中where的高级使用方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。有时候项目中需要进行多个字段搜索就可以用到此方法在Laravel中的可
2023-06-08

如何在 Java 集合中应用 hashCode 方法?(hashCode方法在Java集合中的应用)

在Java编程中,hashCode方法在Java集合中扮演着重要的角色。它主要用于确定对象在哈希表中的存储位置,从而实现高效的存储和检索。本文将详细介绍hashCode方法在Java集合中的应用。一
如何在 Java 集合中应用 hashCode 方法?(hashCode方法在Java集合中的应用)
Java2024-12-18

OpenTelemetry Java SDK 高级用法解析

这篇文章主要介绍了OpenTelemetry Java SDK 的高级用法示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-15

超越像素:Java中的高级图像处理方法

在Java中,你可以通过处理图像像素来实现图像模糊。常用的图像模糊算法是高斯模糊算法,它通过对图像中的每个像素及其周围像素进行加权平均来实现模糊效果。

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录