消息发布者向RabbitMQ进行消息投递时默认情况下是不返回发布者该条消息在broker中的状态的,也就是说发布者不知道这条消息是否真的抵达RabbitMQ的broker之上,也因此会发生消息丢失的情况。

对此,RabbitmQ提供了两种解决方案(以官方提供的SDK为例)

1.通过AMOP提供的事务机制:

C#代码:

                try
{
channel.TxSelect();
channel.BasicPublish("yu.exchange", "yu.1", props, msg);
channel.TxCommit();
}
catch (Exception ex)
{
channel.TxRollback();
}

java代码是一样的操作。。。

        byte[] msg = "hello".getBytes();
try {
channel.txSelect();
channel.basicPublish("yu.exchange", "yu.1", MessageProperties.PERSISTENT_TEXT_PLAIN, msg);
channel.txCommit();
} catch (Exception ex) {
channel.txRollback();
}

事务开启,提交,回滚都有了。。。

2.Conform模式,也就是官网推荐的消息批量提交的方式

Conform模式主要包含两种编程模式,一种同步的,一种异步通知的:

同步回调的调用方式与事务模式差不多

C#代码:

                channel.ConfirmSelect();
byte[] msg = Encoding.UTF8.GetBytes("hello");
channel.BasicPublish("yu.exchange1", "yu.1", props, msg);
bool success = channel.WaitForConfirms(new TimeSpan(, , ));
Console.WriteLine(success);

Java代码:

        byte[] msg = "hello".getBytes();
channel.confirmSelect();
channel.basicPublish("yu.exchange", "yu.1", MessageProperties.PERSISTENT_TEXT_PLAIN, msg);
boolean success = channel.waitForConfirms();

通道Channel开启Conform,在发送完消息后可以通过WaitForConfirm等待消息的投递结果,这里有个可选参数,就是阻塞等待的时间,如果返回结果为false则表示消息投递失败,则发送端这时候也就可以采取重试之类的策略了。

异步回调的方式也就是通道订阅RabbitMQ的发送完毕确认事件,消息投递成功会回调这个方法给发送方,回调的参数包含当前消息在该通道中发送的编号DeliveryTag(批量提交的时候可以根据这个编号对应提交集合的索引,保证对应集合索引上的消息可靠投递),的最大值是9223372036854775807

C#代码:

           channel.BasicAcks += (sender, eventArgs) =>
{
ulong tag = eventArgs.DeliveryTag;
};
channel.BasicReturn += (sender, eventArgs) =>
{ };
byte[] msg = Encoding.UTF8.GetBytes("hello");
channel.BasicPublish("yu.exchange1", "yu.1", true, props, msg);

Java代码:

 channel.addConfirmListener(new ConfirmListener() {
public void handleAck(long l, boolean b) throws IOException {
System.out.println(l);
} public void handleNack(long l, boolean b) throws IOException {
System.out.println(l);
}
});
channel.addReturnListener(new ReturnListener() {
public void handleReturn(int i, String s, String s1, String s2, AMQP.BasicProperties basicProperties, byte[] bytes) throws IOException {
System.out.println("响应状态码-ReplyCode:"+i);
System.out.println("响应内容-ReplyText:"+s);
System.out.println("Exchange:"+s1);
System.out.println("RouteKey"+s2);
System.out.println("投递失败的消息:"+ new String(bytes,"UTF-8") );
            }
});
byte[] msg = "hello".getBytes();
channel.confirmSelect();
channel.basicPublish("yu.exchange1", "yu.1",true, MessageProperties.PERSISTENT_TEXT_PLAIN, msg);

代码中多订阅了一个BasicReturn事件(addReturnListener),当消息被RabbitMQ拒绝或者说没有成功投递的时候,则会触发这个方法,当然想要获取详细信息则需要设置mandatory参数为true,也就是basicPublish("yu.exchange1", "yu.1",true, MessageProperties.PERSISTENT_TEXT_PLAIN, msg);中的第三个参数。

队列中新建一个yu.exchange1的交换机然后不绑定队列的情况下则会投递失败的时间;

RabbitMQ如何保证发送端消息的可靠投递的更多相关文章

  1. RabbitMQ如何保证发送端消息的可靠投递-发生镜像队列发生故障转移时

    上一篇最后提到了mandatory这个参数,对于设置mandatory参数个人感觉还是很重要的,尤其在RabbitMQ镜像队列发生故障转移时. 模拟个测试环境如下: 首先在集群队列中增加两个镜像队列的 ...

  2. IM消息送达保证机制实现(二):保证离线消息的可靠投递

    1.前言 本文的上篇<IM消息送达保证机制实现(一):保证在线实时消息的可靠投递>中,我们讨论了在线实时消息的投递可以通过应用层的确认.发送方的超时重传.接收方的去重等手段来保证业务层面消 ...

  3. IM系统中如何保证消息的可靠投递(即QoS机制)(转)

    消息的可靠性,即消息的不丢失和不重复,是im系统中的一个难点.当初qq在技术上(当时叫oicq)因为以下两点原因才打败了icq:1)qq的消息投递可靠(消息不丢失,不重复)2)qq的垃圾消息少(它an ...

  4. RabbitMQ 消息的可靠投递

    mq 提供了两种方式确认消息的可靠投递 confirmCallback 确认模式 returnCallback 未投递到 queue 退回模式 在使用 RabbitMQ 的时候,作为消息发送方希望杜绝 ...

  5. IM系统中如何保证消息的可靠投递(即QoS机制)

      消息的可靠性,即消息的不丢失和不重复,是im系统中的一个难点.当初qq在技术上(当时叫oicq)因为以下两点原因才打败了icq:1)qq的消息投递可靠(消息不丢失,不重复)2)qq的垃圾消息少(它 ...

  6. springboot rabbitMQ 死信对列 实现消息的可靠消费

    1 引入 maven 依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...

  7. 在服务端处理同步发送小消息的性能上Kafka>RocketMQ>RabbitMQ

    在发送小消息的场景中,三个消息中间件的表现区分明显: Kafka的吞吐量高达17.3w/s,远超其他两个产品.这主要取决于它的队列模式保证了写磁盘的过程是线性IO.此时broker磁盘IO已达瓶颈. ...

  8. 【RabbitMQ】如何进行消息可靠投递【上篇】

    说明 前几天,突然发生线上报警,钉钉连发了好几条消息,一看是RabbitMQ相关的消息,心头一紧,难道翻车了? [橙色报警] 应用[xxx]在[08-15 16:36:04]发生[错误日志异常],al ...

  9. 【RabbitMQ】如何进行消息可靠投递【下篇】

    说明 上一篇文章里,我们了解了如何保证消息被可靠投递到RabbitMQ的交换机中,但还有一些不完美的地方,试想一下,如果向RabbitMQ服务器发送一条消息,服务器确实也接收到了这条消息,于是给你返回 ...

随机推荐

  1. Hello world &博客客户端试用

    第一篇博客,使用 open live writer客户端进行测试,下载地址见http://openlivewriter.org/,软件为英文,但配置比较简单,选择“其他博客类型”就ok. 同时安装了语 ...

  2. [WEB面试题] web前端面试题JavaScript第一弹,个人整理部分面试题汇总

    以下内容仅供参考,成年人不讲对错只讲利弊 1.什么是JavaScript原型链?如何理解 JavaScript中的每个对象都有一个prototype属性,我们称之为原型 原型的值是一个对象有自己的原型 ...

  3. 如何利用API导出带有页眉页脚的excel

     在报表中设置的页眉页脚在页面中是看不到的,如下图: 页面中的效果: 在打印的时候,可以看到页眉页脚的效果: 那么,如果将页眉页脚导入到导出的excel中呢.我们可以通过API来进行设置: < ...

  4. 【Python】Java程序员学习Python(七)— 文本类详解(字符串、str)

    如果一个女孩子喜欢看龙猫,那么请珍惜她,呵护她 任何一门语言,字符串总是最基本也是最需要掌握的一个变量,想想入门的Hello World,输出的就是字符串. 官方文档:https://docs.pyt ...

  5. local_listener参数的作用!

    转自:http://warehouse.itpub.net/post/777/472788 pmon只会动态注册port等于1521的监听,否则pmon不能动态注册listener,要想让pmon动态 ...

  6. 【转】教你弄清 OSX 的睡眠模式,以及合法的禁止产生 sleepimage

    原文链接 因为之前用的是网上流传的土法来禁止生成 sleepimage,尝到了苦头,而且2次! 大家知道 OSX 有几种睡眠模式,其中 hibernatemode 可以是 0 (传统睡眠方式,不生成 ...

  7. 1 Java程序文件中函数起始行和终止行在程序文件位置中的判定__抽象语法树方法

    应用需求: 实现对BigCloneBench中函数体的克隆检测,必须标注出起始行号和终止行号. 问题: 给定一个Java文件,从中提取出每个函数的起始行和终止行. 难点: 这个问题的难点在于,对于Ja ...

  8. Linux命令行得到系统IP

    输入ifconfig得到 eth0 Link encap:Ethernet HWaddr :::2E:9A: inet addr:192.168.1.1 Bcast:192.168.1.255 Mas ...

  9. zTree设置异步加载后展开

    //不能直接配置展开属性 因为没有数据,需要添加回调函数,异步加载成功展开 callback: { onAsyncSuccess: zTreeOnAsyncSuccess } //异步加载成功回调函数 ...

  10. Oracle创建Rman备份专用账户

    有时会因为信息安全需要,创建备份所需的专用账户,不适用sys等用户.可以使用如下方式:create user rman_ycr identified by oracle;grant create se ...