以下转自:http://blog.csdn.net/yangbutao/article/details/10395599

rabbitMQ中consumer通过建立到queue的连接,创建channel对象,通过channel通道获取message, Consumer可以声明式的以API轮询poll的方式主动从queue的获取消息,也可以通过订阅的方式被动的从Queue中消费消息, 最近翻阅了基于java的客户端的相关源码,简单做个分析。 编程模型伪代码如下: ConnectionFactory factory = new ConnectionFactory(); Connection conn = factory.newConnection(); Channel channel=conn.createChannel(); 创建Connection需要指定MQ的物理地址和端口,是socket tcp物理连接,而channel是一个逻辑的概念,支持在tcp连接上创建多个MQ channel 以下是基于channel上的两种消费方式。

1、Subscribe订阅方式 boolean autoAck = false; channel.basicConsume(queueName, autoAck, "myConsumerTag",      new DefaultConsumer(channel) {          @Override          public void handleDelivery(String consumerTag,                                     Envelope envelope,                                     AMQP.BasicProperties properties,                                     byte[] body)              throws IOException          {              String routingKey = envelope.getRoutingKey();              String contentType = properties.contentType;              long deliveryTag = envelope.getDeliveryTag();              // (process the message components here ...)              channel.basicAck(deliveryTag, false);          }      });

订阅方式其实是向queue注册consumer,通过rpc向queue server发送注册consumer的消息,rabbitMQ Server在收到消息后,根据消息的内容类型判断这是一个订阅消息, 这样当MQ 中queue有消息时,会自动把消息通过该socket(长连接)通道发送出去。 参见ChannelN中的方法     public String basicConsume(String queue, boolean autoAck, String consumerTag,                                boolean noLocal, boolean exclusive, Map<String, Object> arguments,                                final Consumer callback)         throws IOException     {     ......         rpc((Method)             new Basic.Consume.Builder()              .queue(queue)              .consumerTag(consumerTag)              .noLocal(noLocal)              .noAck(autoAck)              .exclusive(exclusive)              .arguments(arguments)             .build(),             k);

try {             return k.getReply();         } catch(ShutdownSignalException ex) {             throw wrap(ex);         }     }

Consumer接收消息的过程: 创建Connection后,会启动MainLoop后台线程,循环从socket(FrameHandler)中获取数据包(Frame),调用channel.handleFrame(Frame frame)处理消息,     public void handleFrame(Frame frame) throws IOException {         AMQCommand command = _command;         if (command.handleFrame(frame)) { // 对消息进行协议assemble             _command = new AMQCommand(); // prepare for the next one             handleCompleteInboundCommand(command);//对消息消费处理         }     } ChannelN.handleCompleteInboundCommand        ---ChannelN.processAsync            ----dispatcher.handleDelivery                  ---QueueingConsumer.handleDelivery                      ---this._queue.add(new Delivery(envelope, properties, body));//消息最终放到队列中 每个Consumer都有一个BlockQueue,用于缓存从socket中获取的消息。 接下来,Consumer对象就可以调用api来从客户端缓存的_queue中依次获取消息,进行消费,参见QueueingConsumer.nextDelivery()

对于这种长连接的方式,没看到心跳功能,以防止长连接的因网络等原因连接失效

2、poll API方式 ChannelN: GetResponse basicGet(String queue, boolean autoAck) 这种方式比较简单,直接通过RPC从MQ Server端获取队列中的消息

RabbitMQ Consumer获取消息的两种方式(poll,subscribe)解析的更多相关文章

  1. java动态获取WebService的两种方式(复杂参数类型)

    java动态获取WebService的两种方式(复杂参数类型) 第一种: @Override public OrderSearchListRes searchOrderList(Order_Fligh ...

  2. RabbitMQ实现延时消息的两种方法

    目录 RabbitMQ实现延时消息的两种方法 1.死信队列 1.1消息什么时候变为死信(dead-letter) 1.2死信队列的原理 1.3 代码实现 1.4死信队列的一个小坑 2 .延时插件 2. ...

  3. MyBatis获取参数值的两种方式

    MyBatis获取参数值的两种方式:${}和#{} ${}的本质就是字符串拼接,#{}的本质就是占位符赋值 ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单 ...

  4. rabbitmq 实现延迟队列的两种方式

    原文地址:https://blog.csdn.net/u014308482/article/details/53036770 ps: 文章里面延迟队列=延时队列 什么是延迟队列 延迟队列存储的对象肯定 ...

  5. (先导)Git Api对接:获取private_token的两种方式

    " Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理.在公司一般用于代码管理:开发用例管理平台时我们选择使用git来管理用例,期间使用了很多git ap ...

  6. Spring使用JMS传递消息的两种方式

    方式一:同步收发消息,使用JMS template 消费者阻塞等待消息的到来. 方式二:异步收发消息,使用message listener container 消费者提供一个listener,注册一个 ...

  7. HttpClient获取Cookie的两种方式

    转载:http://blog.csdn.net/zhangbinu/article/details/72777620 一.旧版本的HttpClient获取Cookies p.s. 该方式官方已不推荐使 ...

  8. java实现MQ消息收发两种方式

    定义: 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们.简单理解:蓝牙配对 jar包依赖: <!-- ...

  9. node 创建静态web服务器(下)(处理异步获取数据的两种方式)

    接上一章. 上一章我们说创建的静态web服务器只能识别html,css,js文件,功能较为单一,且图片格式为text/html,这是不合理的. 本章,我们将解决该问题. 这里,我们先准备好一个json ...

随机推荐

  1. Properties 集合

    Map Hashtable Properties 特点: 该集合中的键和值都是字符串类型 集合中的数据可以保存到流中, 或者从流中获取 应用: 通常该集合用于操作以键值对形式存在的配置文件 常用方法: ...

  2. ATA接口寄存器描写叙述

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/mao0514/article/details/32135815 ATA接口寄存器描写叙述   .AT ...

  3. hexo+yilia主题博客如何添加图标icon

    1. 先去比特虫网站做icon图标 2. 图片放到hexo/source/img文件夹下 3. 找到hexo\themes\modernist\layout_partial\head.ejs,设置为 ...

  4. 使用Ehcache缓存同步启动时抛出异常net.sf.ehcache.CacheException: Can't assign requested address

    这个问题在插入公司内网网线的时候不会复现,由于我使用的是公司无线网络,故导致此问题. 具体解决办法是:在启动服务时,指定使用默认ipv4的网络接口.可以在启动jvm时添加参数-Djava.net.pr ...

  5. python 多进程使用Queue通信的例子

    import time from multiprocessing import Process,Queue MSG_QUEUE = Queue(5) def startA(msgQueue): whi ...

  6. django【orm操作】

    一.ORM表结构 class Publisher(models.Model): name = models.CharField(max_length=30, verbose_name="名称 ...

  7. PAT 天梯赛 L1-001 【水】

    L1-001. Hello World 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 这道超级简单的题目没有任何输入. 你只需要在一行中输 ...

  8. js实现删除弹框确认

    JSP页面代码如下: <%@ page language="java" contentType="text/html; charset=UTF-8"%&g ...

  9. for_each用法

    for_each()是个function template #include <algorithm>头文件说明 template<class _InIt, class _Fn1> ...

  10. 双摄像头测距的OpenCV实现

    http://blog.csdn.net/scyscyao/article/details/5562024 版权声明:本文为博主原创文章,未经博主允许不得转载. 虽然最近注意力已经不可遏制地被神经科学 ...