异步通信rabbitmq——消息重试
目标:
利用RabbitMQ实现消息重试和失败处理,实现可靠的消费消费。在消息消费异常时,自动延时将消息重试,当重试超过一定次数后,则列为异常消息,等待后续特殊处理。
准备:
TTL:Time-To-Live,通过给消息、队列设置过期时间(单位:毫秒),来控制消息、队列的生命周期。在达到时间后,消息会变成dead message。
Dead Letter Exchanges:同普通的exchange无区别
消息重制本质是通过消息转发来实现的。消息转发的触发是:
rejected - the message was rejected with requeue=false,
expired - the TTL of the message expired; or
maxlen - the maximum allowed queue length was exceeded.
这里,我们使用expired来实现。给消息设置TTL,到期后消息未被消费,则会变成dead messager,转发到dead letter exchange。
流程图:
实现:
1、创建三个exchange。没有特殊要求
2、创建三个queue。
clickQueue@retry作为重试队列,需要特殊处理:
x-dead-letter-exchange: clickExchange
x-dead-letter-routing-key: clickKey
x-message-ttl: 30000
3、处理代码
public void retry() throws IOException {
//消息消费
GetResponse getResponse = null;
try {
getResponse = rabbitUtil.fetch(DQConstant.CLICK_QUEUE_NAME, false);
/**
* 业务处理
*/
throw new RuntimeException("错粗了");
} catch (Exception e) {
if(null != getResponse) {
long retryCount = getRetryCount(getResponse.getProps());
if(retryCount > 3) {
//重试超过3次的,直接存入失败队列
AMQP.BasicProperties properties = getResponse.getProps();
Map<String, Object> headers = properties.getHeaders();
if(null == headers) {
headers = new HashMap<>();
}
properties.builder().headers(headers);
rabbitUtil.send(DQConstant.CLICK_FAILED_EXCHANGE_NAME, DQConstant.CLICK_FAILED_ROUTING_KEY, properties, getResponse.getBody());
} else {
//重试不超过3次的,加入到重试队列
AMQP.BasicProperties properties = getResponse.getProps();
Map<String, Object> headers = properties.getHeaders();
if(null == headers) {
headers = new HashMap<>();
}
properties.builder().headers(headers);
rabbitUtil.send(DQConstant.CLICK_RETRY_EXCHANGE_NAME, DQConstant.CLICK_RETRY_ROUTING_KEY, properties, getResponse.getBody());
}
}
}
if(null != getResponse) {
rabbitUtil.ack(getResponse);
}
}
private long getRetryCount(AMQP.BasicProperties properties) {
long retryCount = 0;
Map<String, Object> headers = properties.getHeaders();
if(null != headers) {
if(headers.containsKey("x-death")) {
List<Map<String, Object>> deathList = (List<Map<String, Object>>) headers.get("x-death");
if(!deathList.isEmpty()) {
Map<String, Object> deathEntry = deathList.get(0);
retryCount = (Long)deathEntry.get("count");
}
}
}
return retryCount;
}
4、x-death的使用:message在转换成dead letter时,会在其header里添加一个名为x-death的数组。数组元素就是一次dead lettering event的记录。包含count:消息几次变成了dead letter。
总结:
此处只是本人的拙见。如有更好的提议,欢迎拍砖。
---------------------
作者:洛杉矶的管理局
来源:CSDN
原文:://blog.csdn.net/qq_18991441/article/details/80692255
版权声明:本文为博主原创文章,转载请附上博文链接!
异步通信rabbitmq——消息重试的更多相关文章
- Sprinboot 整合 RabbitMQ,RabbitMQ 消息重试机制
当消费者消费消息的时候,出现错误,RabbitMQ 本身会有
- rabbitmq~消息失败后重试达到 TTL放到死信队列(事务型消息补偿机制)
这是一个基于消息的分布式事务的一部分,主要通过消息来实现,生产者把消息发到队列后,由消费方去执行剩下的逻辑,而当消费方处理失败后,我们需要进行重试,即为了最现数据的最终一致性,在rabbitmq里,它 ...
- 基于ASP.NET Core 5.0使用RabbitMQ消息队列实现事件总线(EventBus)
文章阅读请前先参考看一下 https://www.cnblogs.com/hudean/p/13858285.html 安装RabbitMQ消息队列软件与了解C#中如何使用RabbitMQ 和 htt ...
- rabbitmq消息消费者
pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:// ...
- (五)RabbitMQ消息队列-安装amqp扩展并订阅/发布Demo(PHP版)
原文:(五)RabbitMQ消息队列-安装amqp扩展并订阅/发布Demo(PHP版) 本文将介绍在PHP中如何使用RabbitMQ来实现消息的订阅和发布.我使用的系统依然是Centos7,为了方便, ...
- RabbitMQ消息丢失问题和保证消息可靠性-消费端不丢消息和HA(二)
继续上篇文章解决RabbitMQ消息丢失问题和保证消息可靠性(一) 未完成部分,我们聊聊MQ Server端的高可用和消费端如何保证消息不丢的问题? 回归上篇的内容,我们知道消息从生产端到服务端,为了 ...
- RabbitMQ消息幂等性问题
文章目录 1. 什么是幂等性?1.1 消息队列的幂等性1.2 模拟重试机制1.2.1 生产者代码1.2.2 消费者代码1.2.3 消费者 application.yml 配置2. 如何保证消息幂等性, ...
- SpringCloud之RabbitMQ消息队列原理及配置
本篇章讲解RabbitMQ的用途.原理以及配置,RabbitMQ的安装请查看SpringCloud之RabbitMQ安装 一.MQ用途 1.同步变异步消息 场景:用户下单完成后,发送邮件和短信通知. ...
- RabbitMQ消息可靠性传输
消息的可靠性投递是使用消息中间件不可避免的问题,不管是使用kafka.rocketMQ或者rabbitMQ,那么在RabbitMQ中如何保证消息的可靠性投递呢? 先再看一下RabbitMQ消息传递的流 ...
随机推荐
- $python正则表达式系列(5)——零宽断言
本文主要总结了python正则零宽断言(zero-length-assertion)的一些常用用法. 1. 什么是零宽断言 有时候在使用正则表达式做匹配的时候,我们希望匹配一个字符串,这个字符串的前面 ...
- HASH、HASH函数、HASH算法的通俗理解
之前经常遇到hash函数或者经常用到hash函数,但是hash到底是什么?或者hash函数到底是什么?却很少去考虑.最近同学去面试被问到这个问题,自己看文章也看到hash的问题.遂较为细致的追究了一番 ...
- MyBatis传入多个参数 ,List集合
一.单个参数: public List<XXBean> getXXBeanList(String xxCode); <select id="getXXXBeanList&q ...
- Linux yum源码包安装和卸载
Linux 下的绝大多数源码包都是用 C 语言编写的,还有少部分是用 C++ 等其他程序语言编写的.所以,要想安装源码包,必须安装 C 语言编译器 gcc(如果是用 C++ 编写的程序,则还需要安装 ...
- IIS部署PHP项目并与mysql完美结合
在上一篇文章中,提到iis与apache共用80端口,但是发现很多问题,例如 IIS网站有支付功能,而微信支付是不支持带有端口的网址的,虽然通过apche代理,在外面看来没有端口,可是内部还是避免不了 ...
- CentOS/Linux 卸载MATLAB
rm -rf /usr/local/MATLAB/R2012arm /usr/local/bin/matlab /usr/local/bin/mcc /usr/local/bin/mex /usr/l ...
- 织梦dedecms 自带采集的缩略图地址后面有“/”斜杠的解决方法
本来想偷懒在网上找一些文档去解决织梦采集缩略图地址带“/”的问题的,可是找了找发现没有人写出解决方法,只好自己动手了. 过程很复杂,找了问题的原因也是找了半天,自己一点一点的测试.最后找到了问题所在. ...
- hadoop 指定 key value分隔符
原文:http://wingmzy.iteye.com/blog/1260570 hadoop中的map-reduce是处理<key,value>这样的键值对,故指定<key,val ...
- super和this 在构造方法上的用法
super Super()表示调用父类的构造方法.如果没有定义构造方法,那么就会调用父类的无参构造方法,即super(). this 在构造方法中,this表示本类的其他构造方法:student(st ...
- API是什么?——回答:接口。(待)
基础打不够啊,一句话问倒我.第一反应是像java,matlab之类的api,下个小文件,然后安装到电脑上,可以很方便的查看一些东西. 但是一般公司的对外api不可能做的像java这样,还专门提供一个可 ...