rabbitmq的高级特性:

  如何保障消息的百分之百成功?

  要满足4个条件:生产方发送出去,消费方接受到消息,发送方接收到消费者的确认信息,完善的消费补偿机制

  解决方案,1)消息落库,进行消息状态打标

  该解决方案需要对对数据库进行两次io操作,如果数据量很大,将会导致瓶颈的发生,本流程是首先将业务入库,发送消息前,将发送的消息入库消息状态可设置为0,两次写入数据库后,发送消息,消息发送后,mq broker 接收并处理消息,完成后发送回馈消息确认信息,同过确认监听服务器,监听到确认消息后,将其数据库状态更改为1,说明消息发送成功,但是过程中可能出现各种情况导致不能反馈消息,我们需要在添加一个定时轮询任务,比如说设置最大轮询次数为3,时间间隔为5min,每一次当超过5分钟就去检查一次数据库消息状态,如果还是0则,再次发送消息,知道消息状态变为1为止。

  2)延迟投递,二次确认,回调检查

  该模式适用于高并发的场景,也就是并发量非常的,对系统性能要求较高的场合,该模式减少一次主业务的io操作,首先业务落库,然后生成两条消息,首先发出去一次消息,然后5min之后再次发送消息(延迟投递),第一条发送后,broker端收到后转给消费端,正常处理后,发送一个相应消息(再次生成一条的消息)投递出去step4:send confirm,发送到callback服务中,如果callback服务收确认消息,那么callback将消息写入数据库,5min后发送的第二条消息,进入broker中,此时,broker将消息投递到callback中的监听,收到后检查数据库,如果检查消息已经存在,说明消费者正常消费,如果,因各种情况发现消费者没有正产消费,那么callback要进行补偿,发起一个RPC通信告诉上游说消息发送失败,上游程序再次生成消息,重新走上述流程。

幂等性:在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。消息重复投递,或者高并发下,消息仅仅消费一次。

消息确认模式:

生产方:

 package com.zxy.demo.rabbitmq;

 import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmListener;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; public class Producter { public static void main(String[] args) throws IOException, TimeoutException {
// TODO Auto-generated method stub
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.10.110");
factory.setPort(5672);
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
Connection conn = factory.newConnection();
Channel channel = conn.createChannel();
String exchange001 = "exchange_001";
String queue001 = "queue_001";
String routingkey = "mq.topic";
String body = "hello rabbitmq!";
// 添加消息确认模式========消息确认模式重要添加
channel.confirmSelect();
channel.basicPublish(exchange001, routingkey, null, body.getBytes());
// 添加一个确认监听========消息确认模式重要添加
channel.addConfirmListener(new ConfirmListener() { @Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
System.out.println("-----------nck------------"+deliveryTag); } @Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
System.out.println("-----------ck------------"+deliveryTag); }
});
} }

消费方:

 package com.zxy.demo.rabbitmq;

 import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; public class Receiver { public static void main(String[] args) throws IOException, TimeoutException {
// TODO Auto-generated method stub
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.10.110");
factory.setPort(5672);
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
Connection conn = factory.newConnection();
Channel channel = conn.createChannel();
String exchange001 = "exchange_001";
String queue001 = "queue_001";
String routingkey = "mq.*";
channel.exchangeDeclare(exchange001, "topic", true, false, null);
channel.queueDeclare(queue001, true, false, false, null);
channel.queueBind(queue001, exchange001, routingkey);
// 自定义消费者
MyConsumer myConsumer = new MyConsumer(channel);
// 进行消费(消费queue001队列中的消息进行消费,签收模式为自动签收,消费的具体处理类是myConsumer)
channel.basicConsume(queue001, true, myConsumer);
} }

自定义消费类:

 package com.zxy.demo.rabbitmq;

 import java.io.IOException;

 import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope; /**
* 可以继承,可以实现,实现的话要覆写的方法比较多,所以这里用了继承
*
*/
public class MyConsumer extends DefaultConsumer{
private Channel channel;
public MyConsumer(Channel channel) {
super(channel);
// TODO Auto-generated constructor stub
this.channel=channel;
} @Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
System.out.println("消费标签:"+consumerTag);
System.out.println("envelope.getDeliveryTag():==="+envelope.getDeliveryTag());
System.out.println("envelope.getExchange():==="+envelope.getExchange());
System.out.println("envelope.getRoutingKey():==="+envelope.getRoutingKey());
System.out.println("body:==="+new String(body));
} }

确认模式,主要点有两个,一、在channel上添加确认模式channel.comfirmSelect(),

二、添加确认监听器,实现AK和NAK两个方法来处理两种返回情况。

返回模式大同小异:返回模式需要在发布消息时

采用含有mandatory(托管、强制)参数的消息发布模式,并设置该参数为true========这个与消息确认模式有所区别

true则当消息不可达返回处理消息,如果为false则消息不可达删除消息
channel.basicPublish(exchange001, routingkey, true, null, body.getBytes());

然后添加一个返回监听处理没有正确路由的消息,该监听需要实现处理消息的方法。

这两个模式区别较小,消费端没有什么特别的主要是如果返回模式,路由键让其路由不到消费队列即可使返回监听有动作。

代码如下,仅贴出生产端代码,消费如上:

 package com.zxy.demo.rabbitmq;

 import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmListener;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ReturnListener;
import com.rabbitmq.client.AMQP.BasicProperties; public class Producter { public static void main(String[] args) throws IOException, TimeoutException {
// TODO Auto-generated method stub
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.10.110");
factory.setPort(5672);
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
Connection conn = factory.newConnection();
Channel channel = conn.createChannel();
String exchange001 = "exchange_001";
String queue001 = "queue_001";
String routingkey = "mq.topic.return";
String body = "hello rabbitmq!===============返回模式";
// 采用含有mandatory(托管、强制)参数的消息发布模式,并设置该参数为true========这个与消息确认模式有所区别
channel.basicPublish(exchange001, routingkey, true, null, body.getBytes());
// 添加一个返回监听========消息返回模式重要添加
channel.addReturnListener(new ReturnListener() { @Override
public void handleReturn(int replyCode,
String replyText,
String exchange,
String routingKey,
AMQP.BasicProperties properties,
byte[] body)
throws IOException {
System.out.println("=============return 模式============");
System.out.println("replyCode:"+replyCode+"\n"
+"replyText:"+replyText+"\n"
+"exchange:"+exchange+"\n"
+"routingKey:"+routingKey+"\n"
+"properties:"+properties.getBodySize()+"\n"
+"body:"+new String(body)+"\n"); }
});
} }

Rabbitmq之高级特性——百分百投递消息&消息确认模式&消息返回模式实现的更多相关文章

  1. RabbitMQ的高级特性概念理解

    1.RabbitMQ中的消息如何保障百分之百的投递成功? 答:百分之百的投递成功,方案可以参考下面的2.3. 2.什么是生产者端的可靠性投递? 答:第一步,生产者保障消息的成功发出.第二步,保障Rab ...

  2. RabbitMQ:消息发送确认 与 消息接收确认(ACK)

    默认情况下如果一个 Message 被消费者所正确接收则会被从 Queue 中移除 如果一个 Queue 没被任何消费者订阅,那么这个 Queue 中的消息会被 Cache(缓存),当有消费者订阅时则 ...

  3. Rabbitmq的高级特性

    消息如何保证100%投递成功? 什么是生产端的可靠性投递? 1.保障消息的成功发出 2.保障MQ节点的成功接收 3.发送端收到MQ节点(Broker)确认应答 4.完善的消息补偿机制 BAT互联网大厂 ...

  4. Rabbitmq之高级特性——实现消费端限流&NACK重回队列

    如果是高并发下,rabbitmq服务器上收到成千上万条消息,那么当打开消费端时,这些消息必定喷涌而来,导致消费端消费不过来甚至挂掉都有可能. 在非自动确认的模式下,可以采用限流模式,rabbitmq ...

  5. SpringCloud(六) - RabbitMQ安装,三种消息发送模式,消息发送确认,消息消费确认(自动,手动)

    1.安装erlang语言环境 1.1 创建 erlang安装目录 mkdir erlang 1.2 上传解压压缩包 上传到: /root/ 解压缩# tar -zxvf otp_src_22.0.ta ...

  6. java消息服务学习之JMS高级特性

    将介绍的内容是: 控制消息确认.为发送消息指定选项.创建临时目的地.使用JMS本地事务.异步发送消息 五个方面. 1.控制消息确认 在JMS消息得到确认之前,并不认为它已经成功使用.要成功使用消息,通 ...

  7. 消息中间件——RabbitMQ(七)高级特性全在这里!(上)

    前言 前面我们介绍了RabbitMQ的安装.各大消息中间件的对比.AMQP核心概念.管控台的使用.快速入门RabbitMQ.本章将介绍RabbitMQ的高级特性.分两篇(上/下)进行介绍. 消息如何保 ...

  8. RabbitMQ(二):RabbitMQ高级特性

    RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.作为一名合格的开发者,有必要了解一下相关知识,RabbitMQ(一)已经入门RabbitMQ,本文介绍Rabb ...

  9. 消息中间件——RabbitMQ(八)高级特性全在这里!(下)

    前言 上一篇消息中间件--RabbitMQ(七)高级特性全在这里!(上)中我们介绍了消息如何保障100%的投递成功?,幂等性概念详解,在海量订单产生的业务高峰期,如何避免消息的重复消费的问题?,Con ...

随机推荐

  1. LPS(最长回文子序列)

    (注意:我发现最长回文子序列(Longest Palindromic Subsequence)问题与最长回文子串(Longest Palindromic Substring)不一样,子序列不要求下标一 ...

  2. [经验] Linux 怎么连接 Xshell?

    (1) 首先, 你要先有一个可以正常运行的 Linux 系统, 当然一般情况下我们是把这个系统放在虚拟机里的, 我所使用的是 ubuntu-18.04.2-live-server-amd64.iso ...

  3. ch3 盒模型、定位

    标准盒模型.怪异盒模型 外边距叠加 当两个或者争夺垂直外边距相遇时,他们将形成一个外边距,这个外边距的高度等于两个发生叠加的外边距的高度中的较大者. 当一个元素出现在另一个元素上面时,第一个元素的底外 ...

  4. Android LowMemoryKiller原理分析

    copy from : http://gityuan.com/2016/09/17/android-lowmemorykiller/ frameworks/base/services/core/jav ...

  5. 九 SpringMvc与json交互

    将json输出到页面: 1 加入jar包 2 配置Controller层,开启注解ResponseBody,将json发送到页面: 3 访问url 4 响应json,在形参列表里面加上注解

  6. 守神漏洞扫描器V1.2

    主界面 指纹利用 漏洞库 怎么说呢,个人感觉这个扫描器跟小哲的Test404Fuzzer差不多~ 就是功能多了旁站查询.C段查询.而且这款工具的exp比Test404Fuzzer的多了几个~ 总体来说 ...

  7. INI文件,WritePrivateProfileString()和GetPrivateProfileString()函数----转载

    INI文件就是扩展名为“ini”的文件.在Windows系统中,INI文件是很多,最重要的就是“System.ini”.“System32.ini”和“Win.ini”.该文件主要存放用户所做的选择以 ...

  8. 常用的HBase命令

    进入HBase shell:hbase shell 退出HBase shell:exit 查看HBase中所有的表:list 查看某个表中的记录总数:count 'table name' 查看某个表中 ...

  9. window.onload 方法脚本

    //首先 创建一个函数 function windowOload(func){ var onLoad = window.onload; //如果window.onload没有绑定任何函数 则绑定该函数 ...

  10. 【Linux shell】 while read line

    循环中的重定向或许你应该在其他脚本中见过下面的这种写法:while read linedo …done < file刚开始看到这种结构时,很难理解< file是如何与循环配合在一起工作的. ...