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被废止后老代码如何做的解决方案的更多相关文章

  1. wpf后置代码中的Grid布局以及图片路径的设置

    之前用Grid练习连连看布局时,遇到了几个困惑.此次就把当时的一些收获写出来,供以后翻看. 图片路径可能比较常用,所以就写在第一个了. 在xaml中,设置图片非常简单,只要把图片拷贝到资源目录(这里假 ...

  2. JavaWeb之商品查看后历史记录代码实现

    JavaWeb之商品查看后历史记录代码实现全过程解析. 历史记录思路图: 假设已经访问了商品 :1-2-3 那么历史记录就是1-2-3,如果访问了商品8,那么历史记录就是:8-1-2-3,如果再次访问 ...

  3. 我的Git教程 之 解决 git clone后无代码

    解决 git clone 后无代码 前言:这个教程只适用于像我一样大致理解Git的原理,但是不太记得住Git命令的同学使用.所以具体原理只会提一下,具体可以参见Pro Git. 在另一篇 简明的教程  ...

  4. git 找回 git reset --hard HEAD 后的代码

    下面方法只针对当你本地代码做了 git add 或则 git commit 后又手贱的重置本地代码到上一个版本,导致本地代码丢失的情况. 如果你没有 git add 命令,而直接 git reset ...

  5. script指定src后内部代码无效

    /********** 无效 ***************/ <script type="text/javascript" src=""> fun ...

  6. 只要你用atom修改后保存代码文件的时候,你在chrome上的页面就会自动刷新。

    学习html和css的时候Ctrl+s 以后预览网页需要手动刷新 现在不用了 给chrome安装安装LivePage这个插件. 只要你用atom修改后保存代码文件的时候,你在chrome上的页面就会自 ...

  7. AppCan IDE中有时格式化代码后,代码就运行不了了。

    AppCan IDE中有时格式化代码后,代码就运行不了了.

  8. 判断语句(if...else)if...else语句是在指定的条件成立时执行代码,在条件不成立时执行else后的代码

    判断语句(if...else) if...else语句是在指定的条件成立时执行代码,在条件不成立时执行else后的代码. 语法: if(条件) { 条件成立时执行的代码 } else { 条件不成立时 ...

  9. java虚拟机jvm启动后java代码层面发生了什么?

    java虚拟机jvm启动后java代码层面发生了什么? 0000 我想验证的事情 java代码在被编译后可以被jdk提供的java命令进行加载和运行, 在我们的程序被运行起来的时候,都发生了什么事情, ...

随机推荐

  1. 增加phpmyadmin导入文件上限

    一.修改php配置 修改php配置文件,php.ini upload_max_filesize = 100M post_max_size = 100M 一般修改这2个就行了,然后重启wampserve ...

  2. LPWAN

    典型LPWA技术: 1 Sigfox技术由同名的法国Sigfox公司设计研发,成立于2010年,因为Sigfox网络由Sigfox公司为主导进行全球部署,这样能最大程度保证网络服务质量的统一性和稳定性 ...

  3. The Captain 题解

    20200216题目题解 这是一篇题解祭题解记,但一共就一道题目.(ROS菜大了) 题目如下: The Captain 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x ...

  4. 3种使用MQ实现分布式事务的方式

    1.保证消息传递与一致性 1.1生产者确保消息自主性 当生产者发送一条消息时,它必须完成他的所有业务操作. 如下图: 这保证消费者接受到消息时,生产者已处理完毕相关业务,也就是1PC的基础. 1.2 ...

  5. apache、mysql、php核心、phpmyadmin的安装及相互关联

    1.apache的安装 https://blog.csdn.net/ashendove/article/details/52206198 里面的serverName  就是你在服务中 设置的apach ...

  6. SpringSecurity配置,简单梳理

    生活加油:摘一句子: “我希望自己能写这样的诗.我希望自己也是一颗星星.如果我会发光,就不必害怕黑暗.如果我自己是那么美好,那么一切恐惧就可以烟消云散.于是我开始存下了一点希望—如果我能做到,那么我就 ...

  7. 金币(0)<P2015_1>

    金币 (coin.cpp/c/pas) [问题描述]  国王将金币作为工资,发放给忠诚的骑士.第一天,骑士收到一枚金币:之后两天(第二天和第三天),每天收到两枚金币:之后三天(第四.五.六天),每天收 ...

  8. python中的异常处理:厌而不舍

      什么是异常? ------异常:不正常的情况 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常. 异常是Pytho ...

  9. Jlink不报错的方法

    https://blog.csdn.net/yekui6254/article/details/85272767 方法:安装最新的jlink驱动,按下面网址下载 OllyDBG软件,根据上面说的方法修 ...

  10. 第3节 Scala中的模式匹配:1 - 5

    7.    模式匹配和样例类 Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句.类型检查等.并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配. 7.1 ...