【RabbitMQ】8、RabbitMQ之mandatory和immediate

1. 概述

mandatory和immediate是AMQP协议中basic.publish方法中的两个标识位,它们都有当消息传递过程中不可达目的地时将消息返回给生产者的功能。对于刚开始接触RabbitMQ的朋友特别容易被这两个参数搞混,这里博主整理了写资料,简单讲解下这两个标识位。

mandatory 
当mandatory标志位设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返回给生产者(Basic.Return + Content-Header + Content-Body);当mandatory设置为false时,出现上述情形broker会直接将消息扔掉。

mandatory标志的作用:在消息没有被路由到合适队列情况下会将消息返还给消息发布者,同时我们测试了哪些情况下消息不会到达合适的队列,测试1演示的是创建了exchange但是没有为他绑定队列导致的消息未到达合适队列,测试3演示的是创建了exchange同时创建了queue,但是在将两者绑定的时候,使用的bindingKey和消息发布者使用的rountingKey不一致导致的消息未到达合适队列;

immediate 
当immediate标志位设置为true时,如果exchange在将消息路由到queue(s)时发现对于的queue上么有消费者,那么这条消息不会放入队列中。当与消息routeKey关联的所有queue(一个或者多个)都没有消费者时,该消息会通过basic.return方法返还给生产者。

概括来说,mandatory标志告诉服务器至少将该消息route到一个队列中,否则将消息返还给生产者;immediate标志告诉服务器如果该消息关联的queue上有消费者,则马上将消息投递给它,如果所有queue都没有消费者,直接把消息返还给生产者,不用将消息入队列等待消费者了。


2. mandatory

在生产者通过channle的basicPublish方法发布消息时,通常有几个参数需要设置,为此我们有必要了解清楚这些参数代表的具体含义及其作用,查看channel接口,会发现存在3个重载的basicPublish方法:

void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;
void basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body) throws IOException; void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException;

mandatory和immediate上面已经解释过了,其余的参数分别是: 
exchange:交换机名称 
routingkey:路由键 
props:消息属性字段,比如消息头部信息等等 
body:消息主体部分

本节主要讲述mandatory, 下面我们写一个demo,在RabbitMQ broker中有: 
exchange : exchange.mandatory.test 
queue: queue.mandatory.test 
exchange路由到queue的routingkey是mandatory 
这里先不讲当前的exchange绑定到queue中,即:

channel.basicPublish(exchangeName, "", mandatory, immediate, MessageProperties.PERSISTENT_TEXT_PLAIN, "===mandatory===".getBytes());

详细代码如下:

package com.vms.test.zzh.rabbitmq.self;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; /** * Created by hidden on 2017/2/7. */ public class RBmandatoryTest { public static final String ip = "10.198.197.73"; public static final int port = 5672; public static final String username = "root"; public static final String password = "root"; public static final String queueName = "queue.mandatory.test"; public static final String exchangeName = "exchange.mandatory.test"; public static final String routingKey = "mandatory"; public static final Boolean mandatory = true; public static final Boolean immediate = false; public static void main(String[] args) { try { ConnectionFactory factory = new ConnectionFactory(); factory.setHost(ip); factory.setPort(port); factory.setUsername(username); factory.setPassword(password); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.basicQos(1); channel.basicPublish(exchangeName, "", mandatory, immediate, MessageProperties.PERSISTENT_TEXT_PLAIN, "===mandatory===".getBytes()); // channel.close(); // connection.close(); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } } }

运行,之后通过wireshark抓包工具可以看到如下图所示: 
这里写图片描述

这里可以看到最后执行了basic.return方法,将发布者发出的消息返回给了发布者,查看协议的arguments参数部分可以看到:reply-text字段值为NO_ROUTE,表示消息并没有路由到合适的队列中;

那么我们该怎么获取到没有被正确路由到合适队列的消息呢?这时候可以通过为channel信道设置ReturnListener监听器来实现,具体代码(main函数部分):

try {ConnectionFactory factory = new ConnectionFactory();factory.setHost(ip);factory.setPort(port); factory.setUsername(username); factory.setPassword(password); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.basicQos(1); channel.basicPublish(exchangeName, "", mandatory, immediate, MessageProperties.PERSISTENT_TEXT_PLAIN, "===mandatory===".getBytes()); channel.addReturnListener(new ReturnListener() { public void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties basicProperties, byte[] body) throws IOException { String message = new String(body); System.out.println("Basic.return返回的结果是:"+message); } }); // channel.close(); // connection.close(); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); }

运行结果:

Basic.return返回的结果是:===mandatory===

下面我们来看一下,设置mandatory标志且exchange路由到queue中,代码部分只需要将:

channel.basicPublish(exchangeName, "", mandatory, immediate, MessageProperties.PERSISTENT_TEXT_PLAIN, "===mandatory===".getBytes());

改为

channel.basicPublish(exchangeName, routingKey, mandatory, immediate, MessageProperties.PERSISTENT_TEXT_PLAIN, "===mandatory===".getBytes());

即可。 
通过wireshark抓包如下: 
这里写图片描述
可以看到并不会有basic.return方法被调用。查看RabbitMQ管理界面发现消息已经到达了队列。


3. immediate

在RabbitMQ3.0以后的版本里,去掉了immediate参数的支持,发送带immediate标记的publish会返回如下错误: 
“{amqp_error,not_implemented,”immediate=true”,’basic.publish’}”

为什么移除immediate标记,参见如下版本变化描述: 
Removal of “immediate” flag 
What changed? We removed support for the rarely-used “immediate” flag on AMQP’s basic.publish. 
Why on earth did you do that? Support for “immediate” made many parts of the codebase more complex, particularly around mirrored queues. It also stood in the way of our being able to deliver substantial performance improvements in mirrored queues. 
What do I need to do? If you just want to be able to publish messages that will be dropped if they are not consumed immediately, you can publish to a queue with a TTL of 0. 
If you also need your publisher to be able to determine that this has happened, you can also use the DLX feature to route such messages to another queue, from which the publisher can consume them. 
这段解释的大概意思是:immediate标记会影响镜像队列性能,增加代码复杂性,并建议采用“TTL”和“DLX”等方式替代。

出处:https://yq.aliyun.com/articles/238349?spm=5176.8091938.0.0.EfSZh4

http://www.mamicode.com/info-detail-1673003.html?spm=5176.100239.blogcont238349.8.FAbhIg

转载于:https://www.cnblogs.com/wangzhongqiu/p/7832796.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/399341.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

获取异常信息_如何在 ASP.NET Core 中实现全局异常拦截

异常是一种运行时错误,当异常没有得到适当的处理,很可能会导致你的程序意外终止,这篇就来讨论一下如何在 ASP.Net Core MVC 中实现全局异常处理,我会用一些 样例代码 和 截图 来说明这些概念。全局异常处理其实在 ASP.Net Core MV…

Hadoop学习笔记—15.HBase框架学习(基础知识篇)

Hadoop学习笔记—15.HBase框架学习(基础知识篇) HBase是Apache Hadoop的数据库,能够对大型数据提供随机、实时的读写访问。HBase的目标是存储并处理大型的数据。HBase是一个开源的,分布式的,多版本的,面向列…

二维数组删除_「leetcode」数组:总结篇!(一文搞懂数组题目)

数组理论基础数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力也就是说,想法很简单,但实现起来 可能就不是那么回事了。首先要知道数组在内存中的存储方式&#xff0c…

TextView显示颜色高亮的问题

TextView textView (TextView) findViewById( R.id.tv );String text "<font color\"#d93b3a\">" "快过年了" "</font>" "<font color\"#666666\">" "哈哈哈哈" "</…

开源GIS解决方案,暨GeoServer+OpenLayer结合开发总结

http://linking123.github.io/2018/07/21/%E5%BC%80%E6%BA%90GIS%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%EF%BC%8C%E6%9A%A8GeoServer-OpenLayer%E7%BB%93%E5%90%88%E5%BC%80%E5%8F%91%E6%80%BB%E7%BB%93/ – 0.感叹 – 1.文档说明 – 2.文档内容 — 2.1 GeoServer - 地图服务 —…

TOJ---2621--全排列

这个方法 是超神教我的 --- 全排列的方法太多种了 感觉他这种写的 字典序法 是最简单的 最容易让人接受的 而且在时间复杂度和空间复杂度上 都可以让人接受 我待会将具体每步做法简要写一下...-> 我现在被一个 三角形给 深深烦死了 。。。。。。贴个代码 来 缓解下..... 1 …

月份第一天_4月份的第一天,全省迎来晴暖天气~

2019年4月1日早上好北方新农村准时准点播报~▼▼▼今天是2019年4月1日星期一辽宁的天气小孩的脸说变就变上周末突如其来的一场雪&#xff0c;让辽宁大部分地区“措手不及”已经开始回升的温度瞬间跌落到谷底。但不管怎样&#xff0c;随着节气的更迭&#xff0c;冷空气终究大势已…

Windows系统下搭建Git本地代码库

近由于工作需要&#xff0c;要把工作代码做一下版本管理。工作代码也不方便放到github上&#xff0c;也不想付费建私密库&#xff0c;公司也没几个人&#xff0c;所以就想着搭建一个本地Git版本库&#xff0c;来做版本管理。搭建过程如下。 系统环境&#xff1a;Dell OptiPlex…

mac 下终端 操作svn命令 以及出现证书错误的处理方法

首先&#xff0c;转载地址&#xff1a;http://hi.baidu.com/zhu410289616/item/eaaf160f60eb0dc62f4c6b0e 还有一个地址&#xff1a;http://www.cnblogs.com/heiniuhaha/archive/2011/11/11/2245594.html 解决证书出错&#xff0c;错误见下图&#xff1a; 解决方法&#xff1a;…

文件过滤_jmeter(七)-BeanShell对数据过滤保存文件

在测试中有时需要对参数化数据进行过滤&#xff0c;实现保存到一个文件。如&#xff1a;某项目&#xff0c;从数据库查询到10万条用户数据&#xff0c;因为有的用户没有权限或者过期了&#xff0c;需要对这份数据筛选出来能正常使用的用户。如下使用beanshell实现此功能。原文件…

如何在mac系统下搭建git服务器

https://zhidao.baidu.com/question/1823748339128066228.html 第一步,下载gitblit http://gitblit.com/ 这里当然是选择linux/osx的版本。下载下来是一个.tar.gz的压缩文件&#xff0c;我下载时最新版本是gitblit-1.7.1.tar.gz 第二步&#xff0c;配置gitblit 创建目录&…

【Lucene4.8教程之五】Luke

一、Luke基本内容 1、Luke简介 Luke可用于查看Lucene创建的索引&#xff0c;并对其进行基本操作。 2、创建Luke &#xff08;1&#xff09;从Github上下载源文件 https://github.com/tarzanek/luke &#xff08;2&#xff09;解压文件后&#xff0c;打开DOS窗口&#xff0c;进入…

计算mView在view周围的位置

为什么80%的码农都做不了架构师&#xff1f;>>> /*** 计算mView在view周围的位置** param view** param mMargin mView与view或边界的间距* * titleBarHeight 标题栏的高度* mContext当前的Activity*/private void aroundView(View view, float mMargin) …

c++模板类静态成员变量_一文讲透父子类中静态变量,成员变量初始化顺序原理...

推荐&#xff1a;从面试到入职到离职&#xff0c;我在B站工作的30天时光 爱了爱了&#xff0c;Alibaba顶级MySQL调优手册到手&#xff0c;加薪妥了 爱了爱了&#xff0c;Spring Cloud Alibaba内部微服务架构笔记真的太牛了 本文主要是想分析一下静态变量和成员变量的初始化顺序…

Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(八)

大熊猫猪侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 回到Xcode中,新建一个EndLayer类,继承于CCNode.因为我们得在其类方法中创建实例变量,所以我们得建立几个实例变量的属性.打开EndLayer.h文件,修改内…

转:(图文并茂)SQL Server 2005详细安装过程及配置

1、安装过程 注&#xff1a;在Windows7系统下安装SQL Server 2005时&#xff0c;可能会多次遇到提示兼容性问题的情况&#xff0c;此时不用理会&#xff0c;直接点击“运行程序”即可。首先解压下载到的SQL Server 2005压缩文件&#xff0c;如果还没有这个文件&#xff0c;可以…

2019年java安装步骤_win10的JAVA(jdk)2020年最新版安装教程心得

想学安卓反向解析&#xff0c;前期工作就把我折腾得够呛&#xff0c;java安装教程大多18年之前的&#xff0c;和现在的有一些不同&#xff0c;导致我按照网上的教程折腾了好几天都没安装成功&#xff0c;今天突然成功了&#xff0c;有点开心&#xff0c;迫不及待把自己的一些小…

蛋白质结构域的概念_Chapter1 蛋白质结构与功能2

本次回顾两大点&#xff1a;一、肽二、蛋白质结构————一、肽&#xff1a;概念&#xff1a;肽是由氨基酸通过肽键连接形成的线性分子。如上&#xff0c;该教学图涉及知识&#xff1a;1.肽键生成(最好能将反应式写出来)2.氨基酸残基residue3.肽的方向性N —> C4.肽命名5.肽…

css中的em 简单教程 -- 转

先附上原作的地址: https://www.w3cplus.com/css/px-to-em 习惯性的复制一遍~~~~ -------------------------------我是分界线----------------------------------- 什么是弹性布局&#xff1f; 用户的文字大小与弹性布局 用户的浏览器默认渲染的文字大小是“16px”&#xff0c…

ASP.NET MVC下的四种验证编程方式[续篇]

ASP.NET MVC下的四种验证编程方式[续篇] 原文:ASP.NET MVC下的四种验证编程方式[续篇]在《ASP.NET MVC下的四种验证编程方式》一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式&#xff08;“手工验证”、“标注ValidationAttribute特性”、“让数据类型实现IValida…