【rabbitmq】Queueingconsumer被废止后老代码如何做的解决方案
amqp-client 3.x之前的rabbitmq版本有个消费者的写法是借助于Queueingconsumer的:
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicQos(1);
channel.basicConsume(QUEUE_NAME, false, "consumer_test",consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [X] Received '" + message + "'");
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
break;
}
这个应该是5.x之前的经典写法。但是在4.x的版本QueueingConsumer被标记废止5.x被移除。移除的原因是什么呢?
原来QueueingConsumer内部用LinkedBlockingQueue来存放消息的内容,而LinkedBlockingQueue:一个由链表结构组成的有界队列,照先进先出的顺序进行排序 ,未指定长度的话,默认 此队列的长度为Integer.MAX_VALUE,那么问题来了,如果生产者的速度远远大于消费者的速度,也许没等到队列阻塞的条件产生(长度达到Integer.MAX_VALUE)内存就完蛋了,在老的版本你可以通过设置 rabbitmq的prefetch属性channel.basicQos(prefetch)来处理这个问题如果不设置可能出现内存问题(比如因为网络问题只能向rabbitmq生产不能消费,消费者恢复网络之后就会有大量的数据涌入,出现内存问题,oom fgc等)。
而且最上面的写法很不合理不符合事件驱动,什么时候停止while循环也不能写的很优雅,所以在更高的版本直接被移除。取而代之的是DefaultConsumer,你可以通过扩展DefaultConsumer来实现消费者:
消费的代码:(RabbitMqMessageConsumer是对DefaultConsumer的扩展)
RabbitMqMessageConsumer rpcMessageConsumer = new RabbitMqMessageConsumer(channel,cores);
channel.basicQos(cores);
channel.basicConsume(QUEUE_NAME, true, rpcMessageConsumer);
RabbitMqMessageConsumer代码:
public class RabbitMqMessageConsumer extends DefaultConsumer{
public RabbitMqMessageConsumer(Channel channel) {
super(channel);
}
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
//TODO someting
}
}
其中handleDelivery是处理消息的逻辑。
高版本的解决方案给出了,那么回到我们题目的问题,老代码是按照4.x之前的写的,由于某种原因升级到了5.x了如何做?釜底抽薪的办法就是按照上面的事件驱动的方式重写消费者。折中的办法呢(不想改变老代码的逻辑和结构)。
我就碰到了这样的问题,老代码写了很多的轮子,导致这块代码很难重写。那就只能按照原来QueueingConsumer的写法继续做。解决思路如下:
首先消费的过程还是按照最开始那样:
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicQos(1);
channel.basicConsume(QUEUE_NAME, false, "consumer_test",consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [X] Received '" + message + "'");
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
break;
}
然后实现自己的QueueingConsumer(QueueingConsumer已经移除):
public class QueueingConsumer extends DefaultConsumer{
private LinkedBlockingQueue<Delivery> queue;
public QueueingConsumer(Channel channel) {
super(channel);
queue = new LinkedBlockingQueue<RabbitMqMessageConsumer.Delivery>();
}
public QueueingConsumer(Channel channel,int size) {
super(channel);
queue = new LinkedBlockingQueue<RabbitMqMessageConsumer.Delivery>(size);
}
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
Delivery delivery = new Delivery();
delivery.setBody(body);
delivery.setProperties(properties);
delivery.setEnvelope(envelope);
try {
queue.put(delivery);
} catch (InterruptedException e) {
LogUtils.error(e);
}
}
public Delivery nextDelivery()throws InterruptedException, ShutdownSignalException, ConsumerCancelledException{
return queue.take();
}
public Delivery nextDelivery(long timeout)throws InterruptedException, ShutdownSignalException, ConsumerCancelledException{
return queue.poll(timeout, TimeUnit.MILLISECONDS);
}
public class Delivery{
private BasicProperties properties;
private byte[] body;
private Envelope envelope;
public BasicProperties getProperties() {
return properties;
}
public void setProperties(BasicProperties properties) {
this.properties = properties;
}
public byte[] getBody() {
return body;
}
public void setBody(byte[] body) {
this.body = body;
}
public Envelope getEnvelope() {
return envelope;
}
public void setEnvelope(Envelope envelope) {
this.envelope = envelope;
}
}
}
这样你就能在不修改之前的老代码的情况下升级版本了,当然最好还是重写,这个只能起到个过度
【rabbitmq】Queueingconsumer被废止后老代码如何做的解决方案的更多相关文章
- wpf后置代码中的Grid布局以及图片路径的设置
之前用Grid练习连连看布局时,遇到了几个困惑.此次就把当时的一些收获写出来,供以后翻看. 图片路径可能比较常用,所以就写在第一个了. 在xaml中,设置图片非常简单,只要把图片拷贝到资源目录(这里假 ...
- JavaWeb之商品查看后历史记录代码实现
JavaWeb之商品查看后历史记录代码实现全过程解析. 历史记录思路图: 假设已经访问了商品 :1-2-3 那么历史记录就是1-2-3,如果访问了商品8,那么历史记录就是:8-1-2-3,如果再次访问 ...
- 我的Git教程 之 解决 git clone后无代码
解决 git clone 后无代码 前言:这个教程只适用于像我一样大致理解Git的原理,但是不太记得住Git命令的同学使用.所以具体原理只会提一下,具体可以参见Pro Git. 在另一篇 简明的教程 ...
- git 找回 git reset --hard HEAD 后的代码
下面方法只针对当你本地代码做了 git add 或则 git commit 后又手贱的重置本地代码到上一个版本,导致本地代码丢失的情况. 如果你没有 git add 命令,而直接 git reset ...
- script指定src后内部代码无效
/********** 无效 ***************/ <script type="text/javascript" src=""> fun ...
- 只要你用atom修改后保存代码文件的时候,你在chrome上的页面就会自动刷新。
学习html和css的时候Ctrl+s 以后预览网页需要手动刷新 现在不用了 给chrome安装安装LivePage这个插件. 只要你用atom修改后保存代码文件的时候,你在chrome上的页面就会自 ...
- AppCan IDE中有时格式化代码后,代码就运行不了了。
AppCan IDE中有时格式化代码后,代码就运行不了了.
- 判断语句(if...else)if...else语句是在指定的条件成立时执行代码,在条件不成立时执行else后的代码
判断语句(if...else) if...else语句是在指定的条件成立时执行代码,在条件不成立时执行else后的代码. 语法: if(条件) { 条件成立时执行的代码 } else { 条件不成立时 ...
- java虚拟机jvm启动后java代码层面发生了什么?
java虚拟机jvm启动后java代码层面发生了什么? 0000 我想验证的事情 java代码在被编译后可以被jdk提供的java命令进行加载和运行, 在我们的程序被运行起来的时候,都发生了什么事情, ...
随机推荐
- 吴裕雄 python 神经网络——TensorFlow 多线程队列操作
import tensorflow as tf queue = tf.FIFOQueue(100,"float") enqueue_op = queue.enqueue([tf.r ...
- IDEA 查看字节码
参考:https://www.jianshu.com/p/18953ec8c0b7 打开工具栏 输入参数: 参数: $JDKPath$\bin\javap.exe -c $FileClass$ $Ou ...
- Python语言——map/reduce的用法
Python内建了map()和reduce()函数. 如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Processing on Large Clus ...
- Codeforces Round #592 (Div. 2)G(模拟)
#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;long long a[1000007],b[ ...
- 大道至简第一章JAVA伪代码形式读后感
//愚公移山: public class YuGongYiShan{ //原始需求:“惩山北之塞,出入之迂” //沟通方式:“聚室而谋曰” //项目目标:“毕力平险,指通豫南,达于汉阴” //技术方案 ...
- base64,base32bit加密解密
import base64 str='admin' str=str.encode('utf-8') #加密 bs64=base64.b64encode(str) #解密 debs64=base64.b ...
- Oracle Parallel使用方法
一. 并行查询 并行查询允许将一个sql select语句划分为多个较小的查询,每个部分的查询并发地运行,然后将各个部分的结果组合起来,提供最终的结果,多用于全表扫描,索引全扫描等,大表的扫描和连接. ...
- PTA的Python练习题(二)
继续在PTA上练习Python (从 第2章-5 求奇数分之一序列前N项和 开始) 1. x=int(input()) a=i=1 s=0 while(i<=x): s=s+1/a a=a+2 ...
- python 基础之深浅拷贝
深浅拷贝 s=[[1,2],'fgfgf','cx'] s3=s.copy() print(s) print(s3) 测试 D:\python\python.exe D:/untitled/dir/f ...
- ES6新语法概览
简介 ES6是JavaScript语言的新一代标准,加入了一些新的功能和语法,正式发布于2015年6月,亦称ES2015:该标准由ECMA(欧洲计算机制造联合会)的第39号技术专家委员会(TC39)制 ...