Rabbitmq之高级特性——百分百投递消息&消息确认模式&消息返回模式实现
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之高级特性——百分百投递消息&消息确认模式&消息返回模式实现的更多相关文章
- RabbitMQ的高级特性概念理解
1.RabbitMQ中的消息如何保障百分之百的投递成功? 答:百分之百的投递成功,方案可以参考下面的2.3. 2.什么是生产者端的可靠性投递? 答:第一步,生产者保障消息的成功发出.第二步,保障Rab ...
- RabbitMQ:消息发送确认 与 消息接收确认(ACK)
默认情况下如果一个 Message 被消费者所正确接收则会被从 Queue 中移除 如果一个 Queue 没被任何消费者订阅,那么这个 Queue 中的消息会被 Cache(缓存),当有消费者订阅时则 ...
- Rabbitmq的高级特性
消息如何保证100%投递成功? 什么是生产端的可靠性投递? 1.保障消息的成功发出 2.保障MQ节点的成功接收 3.发送端收到MQ节点(Broker)确认应答 4.完善的消息补偿机制 BAT互联网大厂 ...
- Rabbitmq之高级特性——实现消费端限流&NACK重回队列
如果是高并发下,rabbitmq服务器上收到成千上万条消息,那么当打开消费端时,这些消息必定喷涌而来,导致消费端消费不过来甚至挂掉都有可能. 在非自动确认的模式下,可以采用限流模式,rabbitmq ...
- SpringCloud(六) - RabbitMQ安装,三种消息发送模式,消息发送确认,消息消费确认(自动,手动)
1.安装erlang语言环境 1.1 创建 erlang安装目录 mkdir erlang 1.2 上传解压压缩包 上传到: /root/ 解压缩# tar -zxvf otp_src_22.0.ta ...
- java消息服务学习之JMS高级特性
将介绍的内容是: 控制消息确认.为发送消息指定选项.创建临时目的地.使用JMS本地事务.异步发送消息 五个方面. 1.控制消息确认 在JMS消息得到确认之前,并不认为它已经成功使用.要成功使用消息,通 ...
- 消息中间件——RabbitMQ(七)高级特性全在这里!(上)
前言 前面我们介绍了RabbitMQ的安装.各大消息中间件的对比.AMQP核心概念.管控台的使用.快速入门RabbitMQ.本章将介绍RabbitMQ的高级特性.分两篇(上/下)进行介绍. 消息如何保 ...
- RabbitMQ(二):RabbitMQ高级特性
RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.作为一名合格的开发者,有必要了解一下相关知识,RabbitMQ(一)已经入门RabbitMQ,本文介绍Rabb ...
- 消息中间件——RabbitMQ(八)高级特性全在这里!(下)
前言 上一篇消息中间件--RabbitMQ(七)高级特性全在这里!(上)中我们介绍了消息如何保障100%的投递成功?,幂等性概念详解,在海量订单产生的业务高峰期,如何避免消息的重复消费的问题?,Con ...
随机推荐
- LeetCode 101.对称二叉树 - JavaScript
题目描述:给定一个二叉树,检查它是否是镜像对称的. 题目分析 下面这种二叉树就是镜像对称的,符合题目要求: 1 / \ 2 2 / \ / \ 3 4 4 3 解法 1:递归检查 根据题目" ...
- Python 基础之import导包
首先需要将import内容建立一个大概如下层级的包: 以黑色框为第一级,蓝色框为第二级,棕色框为第三级,红色框为第四级 一.import 引入初识 首先在module.py写入代码如下: xboy = ...
- Lesson 10 Silicon valley
What does the computer industry thrive on apart from anarchy? Technology trends may push Silicon Val ...
- APIView 的请求生命周期
目录 APIView 的请求生命周期 请求解析模块 响应渲染模块 序列化组件 Django 配置 """ 1)应用是否需要在INSTALLED_APPS中注册 在没有使用 ...
- IDEA配置数据库连接失败的问题
今天采用IDEA连接数据库失败了,有几个问题需要注意 首先笔者采用的数据库版本为8.0.17而IDEA自带版本是5.2.26大概,于是首先出现的问题是驱动不匹配,那么就需要换成我自己的版本,配置如下 ...
- JS链接转换为二维码
这里用到一个JQ插件 qrcode.js 下载地址https://github.com/jeromeetienne/jquery-qrcode 先引入 <script src="j ...
- tcp/ip协议学习笔记一
一. 简述 以前在学校学习计算机网络的时候学习多是网络7层模型OSI,了解了一些基本的计算机网络概念和协议通信格式,但是一直没弄明白其中的原理,包括各层之间的关系,应用,还有一些常见的令牌环网到底是什 ...
- 写的一个轻量级javascript框架的设计模式
公司一直使用jQuery框架,一些小的项目还是觉得jQuery框架太过于强大了,于是自己周末有空琢磨着写个自己的框架.谈到js的设计模式,不得不说说js的类继承机制,javascript不同于PHP可 ...
- zabbix4.4安装 centos7+mysql+Nginx
1.安装数据源 # rpm -Uvh https://repo.zabbix.com/zabbix/4.4/rhel/7/x86_64/zabbix-release-4.4-1.el7.noarch. ...
- mac brew redis
1.搜索brew search redis //出现如下 ==> Searching local taps... hiredis redis redis-leveldb redis@2.8 re ...