rabbitmq method之basic.consume
basic.consume指的是channel在 某个队列上注册消费者,那在这个队列有消息来了之后,就会把消息转发到给此channel处理,如果 这个队列有多个消费者,则会采用轮转的方式将消息分发给消息者.
首先是rabbit_reader接收数据包后,解析组装出其中的method,channel方法交给channel处理.具体过程见http://www.cnblogs.com/haoqingchuan/p/4354692.html
channel进程处理basic.consume的方法.先从状态中查看是否已经存在此tag(以channel为域,不同的consumer_tag标识了不同的消费者,每个channel的内的consumer tag必须是唯一的).如果没有查找到则正常,如果未对队列名字命名,则会产生一个uuid来作为队列名.
- handle_method(#'basic.consume'{queue = QueueNameBin,
- consumer_tag = ConsumerTag,
- no_local = _, % FIXME: implement
- no_ack = NoAck,
- exclusive = ExclusiveConsume,
- nowait = NoWait,
- arguments = Args},
- _, State = #ch{consumer_prefetch = ConsumerPrefetch,
- consumer_mapping = ConsumerMapping}) ->
- case dict:find(ConsumerTag, ConsumerMapping) of
- error ->
- QueueName = qbin_to_resource(QueueNameBin, State),
- check_read_permitted(QueueName, State),
- ActualConsumerTag =
- case ConsumerTag of
- <<>> -> rabbit_guid:binary(rabbit_guid:gen_secure(),
- "amq.ctag");
- Other -> Other
- end,
- case basic_consume(
- QueueName, NoAck, ConsumerPrefetch, ActualConsumerTag,
- ExclusiveConsume, Args, NoWait, State) of
- {ok, State1} ->
- {noreply, State1};
- {error, exclusive_consume_unavailable} ->
- rabbit_misc:protocol_error(
- access_refused, "~s in exclusive use",
- [rabbit_misc:rs(QueueName)])
- end;
- {ok, _} ->
- %% Attempted reuse of consumer tag.
- rabbit_misc:protocol_error(
- not_allowed, "attempt to reuse consumer tag '~s'", [ConsumerTag])
- end;
- basic_consume(QueueName, NoAck, ConsumerPrefetch, ActualConsumerTag,
- ExclusiveConsume, Args, NoWait,
- State = #ch{conn_pid = ConnPid,
- limiter = Limiter,
- consumer_mapping = ConsumerMapping}) ->
- case rabbit_amqqueue:with_exclusive_access_or_die(
- QueueName, ConnPid,
- fun (Q) ->
- {rabbit_amqqueue:basic_consume(
- Q, NoAck, self(),
- rabbit_limiter:pid(Limiter),
- rabbit_limiter:is_active(Limiter),
- ConsumerPrefetch, ActualConsumerTag,
- ExclusiveConsume, Args,
- ok_msg(NoWait, #'basic.consume_ok'{
- consumer_tag = ActualConsumerTag})),
- Q}
- end) of
- {ok, Q = #amqqueue{pid = QPid, name = QName}} ->
- CM1 = dict:store(
- ActualConsumerTag,
- {Q, {NoAck, ConsumerPrefetch, ExclusiveConsume, Args}},
- ConsumerMapping),
- State1 = monitor_delivering_queue(
- NoAck, QPid, QName,
- State#ch{consumer_mapping = CM1}),
- {ok, case NoWait of
- true -> consumer_monitor(ActualConsumerTag, State1);
- false -> State1
- end};
- {{error, exclusive_consume_unavailable} = E, _Q} ->
- E
- end.
rabbit_amqqueue.erl
rabbitmq_channel进程向rabbitmq_amqp_process进程发送消息来完成增加消费者的动作
- basic_consume(#amqqueue{pid = QPid, name = QName}, NoAck, ChPid, LimiterPid,
- LimiterActive, ConsumerPrefetchCount, ConsumerTag,
- ExclusiveConsume, Args, OkMsg) ->
- ok = check_consume_arguments(QName, Args),
- delegate:call(QPid, {basic_consume, NoAck, ChPid, LimiterPid, LimiterActive,
- ConsumerPrefetchCount, ConsumerTag, ExclusiveConsume,
- Args, OkMsg}).
rabbit_amqqueue_process.erl
增加consumer,并更新到state中。
- handle_call({basic_consume, NoAck, ChPid, LimiterPid, LimiterActive,
- PrefetchCount, ConsumerTag, ExclusiveConsume, Args, OkMsg},
- _From, State = #q{consumers = Consumers,
- exclusive_consumer = Holder}) ->
- case check_exclusive_access(Holder, ExclusiveConsume, State) of
- in_use -> reply({error, exclusive_consume_unavailable}, State);
- ok -> Consumers1 = rabbit_queue_consumers:add(
- ChPid, ConsumerTag, NoAck,
- LimiterPid, LimiterActive,
- PrefetchCount, Args, is_empty(State),
- Consumers),
- ExclusiveConsumer =
- if ExclusiveConsume -> {ChPid, ConsumerTag};
- true -> Holder
- end,
- State1 = State#q{consumers = Consumers1,
- has_had_consumers = true,
- exclusive_consumer = ExclusiveConsumer},
- ok = maybe_send_reply(ChPid, OkMsg),
- emit_consumer_created(ChPid, ConsumerTag, ExclusiveConsume,
- not NoAck, qname(State1),
- PrefetchCount, Args, none),
- notify_decorators(State1),
- reply(ok, run_message_queue(State1))
- end;
rabbit_queue_consumers.erl
更新进程字典,并为队列增加新消费者.
- add(ChPid, CTag, NoAck, LimiterPid, LimiterActive, Prefetch, Args, IsEmpty,
- State = #state{consumers = Consumers,
- use = CUInfo}) ->
- C = #cr{consumer_count = Count,
- limiter = Limiter} = ch_record(ChPid, LimiterPid),
- Limiter1 = case LimiterActive of
- true -> rabbit_limiter:activate(Limiter);
- false -> Limiter
- end,
- C1 = C#cr{consumer_count = Count + 1, limiter = Limiter1},
- update_ch_record(
- case parse_credit_args(Prefetch, Args) of
- {0, auto} -> C1;
- {_Credit, auto} when NoAck -> C1;
- {Credit, Mode} -> credit_and_drain(
- C1, CTag, Credit, Mode, IsEmpty)
- end),
- Consumer = #consumer{tag = CTag,
- ack_required = not NoAck,
- prefetch = Prefetch,
- args = Args},
- State#state{consumers = add_consumer({ChPid, Consumer}, Consumers),
- use = update_use(CUInfo, active)}.
%%将consumer加入consumers列表里面,也就是后面分发消息的时候会从这个列表里将消息取出
- in(X, 0, { queue, [_] = In, [], 1}) ->
- {queue, [X], In, 2};
- in(X, 0, {queue, In, Out, Len}) when is_list(In), is_list(Out) ->
- {queue, [X|In], Out, Len + 1};
rabbitmq method之basic.consume的更多相关文章
- rabbitmq method之queue.declare
queue.declare即申请队列,首先对队列名作处理,若未指定队列名则随机生成一个,然后查询数据库队列是否已经创建,若创建完成则会申请队列返回 handle_method(#'queue.decl ...
- RabbitMQ channel 参数详解
1.Channel 1.1 channel.exchangeDeclare(): type:有direct.fanout.topic三种durable:true.false true:服务器重启会保留 ...
- RabbitMQ中客户端的Channel类里各方法释义
// The contents of this file are subject to the Mozilla Public License // Version 1.1 (the "Lic ...
- rabbitmq channel参数详解
文章转载自: https://www.cnblogs.com/piaolingzxh/p/5448927.html 部分参数说明有修改 1.Channel 1.1 channel.exchang ...
- rabbitmq channel参数详解【转】
1.Channel 1.1 channel.exchangeDeclare(): type:有direct.fanout.topic三种durable:true.false true:服务器重启会保留 ...
- RabbitMQ Consumer获取消息的两种方式(poll,subscribe)解析
以下转自:http://blog.csdn.net/yangbutao/article/details/10395599 rabbitMQ中consumer通过建立到queue的连接,创建channe ...
- RabbitMQ - Start Up
开始之前 rabbitmq是一个被广泛使用的消息队列,它是由erlang编写的,根据AMQP协议设计实现的. AMQP的主要特征是面向消息.队列.路由(包括点对点和发布/订阅).可靠性.安全. Rab ...
- 探索 OpenStack 之(14):OpenStack 中 RabbitMQ 的使用
本文是 OpenStack 中的 RabbitMQ 使用研究 两部分中的第一部分,将介绍 RabbitMQ 的基本概念,即 RabbitMQ 是什么.第二部分将介绍其在 OpenStack 中的使用. ...
- [译]rabbitmq 2.2 Building from the bottom: queues
我对rabbitmq学习还不深入,这些翻译仅仅做资料保存,希望不要误导大家. You have consumers and producers under your belt, and now you ...
随机推荐
- Android编程容易犯的错误之二
11.不要太相信工具,比如Eclipse里面的断点遇到多线程什么,经常不起作用/走不到,还有就是如果语句为空的也不会走,这时候别太早下结论断点地方出错了, 所以每个工程都应该有日志的开关,通过查看日志 ...
- sql 列转行
原表:转过的表: 代码: ) set @sql = 'select AssetRecordId ' select @sql = @sql + ' , max(case ExtendName when ...
- @Controller和@RestController的区别
1. Controller, RestController的共同点 都是用来表示spring某个类的是否可以接收HTTP请求 2. Controller, RestController的不同点 @C ...
- Multiple dex files define Lcom/google/zxing/BarcodeFormat
解决zxing “Could not find class 'com.goole.zxing.Result”和“Multiple dex files define”问题 时间 2014-04-24 1 ...
- 开发Visual Studio 插件
新建项目,在其他项目类型中找到扩展性,然后新建Visual Studio外接程序,VS中没有这个要安装SDK,http://yunpan.cn/cd27eNczKREwd (提取码:ab29)去下载 ...
- windows批处理语法
写批处理文件,除了了解基本语法外,你还需要熟悉常用的windows命令,那就先看看这篇文章:windows常用命令 #重要说明 文件及目录路径:要使用反斜杠'\',不要使用正斜杠'/' 如:del d ...
- JVM 1.6 GC
JVM调优是一门艺术. JVM调优的重点是减少Major GC的次数,因为Major GC会暂停程序比较长的时间.如果Major GC的次数比较多,意味着应用程序的JVM内存参数需要调整. JVM内存 ...
- CS224d assignment 1【Neural Network Basics】
refer to: 机器学习公开课笔记(5):神经网络(Neural Network) CS224d笔记3--神经网络 深度学习与自然语言处理(4)_斯坦福cs224d 大作业测验1与解答 CS224 ...
- lua52 C API测试代码
//这是一篇lua与C++交互的情景测试 #include <lua.hpp> #include <lauxlib.h> #include <lualib.h> # ...
- 10 Cookie/Session
JSP/EL入门 * SUN提供了开发WEB资源的技术 Servlet/JSP * response.getWriter().write(); ...