worker_pool_worker的作用是用来完成数据操作。

如何获取worker是从worker_pool里获取,并由worker_pool管理。

起动时间:

-rabbit_boot_step({worker_pool,

[{description, "worker pool"},

{mfa, {rabbit_sup, start_supervisor_child,

[worker_pool_sup]}},

{requires, pre_boot},

{enables, external_infrastructure}]}).

在起动顺序中,work_pool是由pre_boot之后,external_infrastructure之后起动的。起动一个worker_pool进程,并起动Wcount个work_pool_worker进程,Wcount是由erlang:system_info(schedulers)决定的。

init([WCount])
->

{ok,
{{one_for_one, 10, 10},

[{worker_pool,
{worker_pool, start_link, []}, transient,

16#ffffffff,
worker, [worker_pool]} |

[{N,
{worker_pool_worker, start_link, []}, transient, 16#ffffffff,

worker,
[worker_pool_worker]} || N <- lists:seq(1, Wcount)]]}}.

worker_pool_worker起动的时候会将通过worke_pool:read(self())来监控起来,并将此进程放置于state中avaliable列表中。当worker_pool_worker
down掉时,worker_pool则会将此进程从avaliable队表中删除掉。

init([])
->

ok
= file_handle_cache:register_callback(?MODULE,
set_maximum_since_use,

[self()]),

ok
= worker_pool:ready(self()),

put(worker_pool_worker,
true),

{ok,
undefined, hibernate,

{backoff,
?HIBERNATE_AFTER_MIN, ?HIBERNATE_AFTER_MIN, ?DESIRED_HIBERNATE}}.

worker_pool.erl

ready(WPid)
-> gen_server2:cast(?SERVER, {ready, Wpid}).

handle_cast({ready,
WPid}, State) ->

erlang:monitor(process,
WPid),

handle_cast({idle,
WPid}, State);

handle_cast({idle,
WPid}, State = #state { available = Avail,

pending
= Pending }) ->

{noreply,

case
queue:out(Pending) of

{empty,
_Pending} ->

State
#state { available = ordsets:add_element(WPid, Avail) };

{{value,
{next_free, From, CPid}}, Pending1} ->

worker_pool_worker:next_job_from(WPid,
CPid),

gen_server2:reply(From,
WPid),

State
#state { pending = Pending1 };

{{value,
{run_async, Fun}}, Pending1} ->

worker_pool_worker:submit_async(WPid,
Fun),

State
#state { pending = Pending1 }

end,
hibernate};

handle_info({'DOWN',
_MRef, process, WPid, _Reason},

State
= #state { available = Avail }) ->

{noreply,
State #state { available = ordsets:del_element(WPid, Avail) },

hibernate};

如果有submit动作,获取空闲的worker,并作

submit(Fun,
ProcessModel) ->

case
get(worker_pool_worker) of

true
-> worker_pool_worker:run(Fun);

_
-> Pid = gen_server2:call(?SERVER, {next_free, self()},
infinity),

worker_pool_worker:submit(Pid,
Fun, ProcessModel)

end.

此时应获取一个空闲的worker_pool_worker,并让此worker装备一下,返回worker
Pid。

handle_call({next_free,
CPid}, _From, State = #state { available =

[WPid
| Avail1] }) ->

worker_pool_worker:next_job_from(WPid,
CPid),

{reply,
WPid, State #state { available = Avail1 }, hibernate};

worker_pool_worker准备工作

next_job_from(Pid,
CPid) ->

gen_server2:cast(Pid,
{next_job_from, Cpid}).

work_pool_worke刚起来的时候state是undefined,当需要自己去完成工作的时候,worker会将work_pool进程监控起来,以便pool在使用自己执行操作的时候且pool异常时能够释放自己。

handle_cast({next_job_from,
CPid}, undefined) ->

MRef
= erlang:monitor(process, CPid),

{noreply,
{from, CPid, MRef}, hibernate};

submit(Pid,
Fun, ProcessModel) ->

gen_server2:call(Pid,
{submit, Fun, self(), ProcessModel}, infinity).

将pool解监控,返回pool执行结果,释放自己,state重回undefined。

handle_call({submit,
Fun, CPid, ProcessModel}, From, {from, CPid, MRef}) ->

erlang:demonitor(MRef),

gen_server2:reply(From,
run(Fun, ProcessModel)),

ok
= worker_pool:idle(self()),

{noreply,
undefined, hibernate};

参考文献:

Erlang:RabbitMQ源码分析 5. worker pool 实现分析. http://m.blog.csdn.net/blog/liaosongbo/39317829

rabbitmq之work_pool的更多相关文章

  1. Erlang pool management -- RabbitMQ worker_pool

    在RabbitMQ中,pool 是以worker_pool 的形式存在的, 其主要用途之一是对Mnesia transaction 的操作. 而在RabbitMQ 中, pool 中的worker 数 ...

  2. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  3. RabbitMq应用二

    在应用一中,基本的消息队列使用已经完成了,在实际项目中,一定会出现各种各样的需求和问题,rabbitmq内置的很多强大机制和功能会帮助我们解决很多的问题,下面就一个一个的一起学习一下. 消息响应机制 ...

  4. 如何优雅的使用RabbitMQ

    RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具.消息队列的使用场景大概有3种: 1.系统集成,分布式系统的设 ...

  5. RabbitMq应用一的补充(RabbitMQ的应用场景)

    直接进入正题. 一.异步处理 场景:发送手机验证码,邮件 传统古老处理方式如下图 这个流程,全部在主线程完成,注册->入库->发送邮件->发送短信,由于都在主线程,所以要等待每一步完 ...

  6. RabbitMq应用一

    RabbitMq应用一 RabbitMQ的具体概念,百度百科一下,我这里说一下我的理解,如果有少或者不对的地方,欢迎纠正和补充. 一个项目架构,小的时候,一般都是传统的单一网站系统,或者项目,三层架构 ...

  7. 缓存、队列(Memcached、redis、RabbitMQ)

    本章内容: Memcached 简介.安装.使用 Python 操作 Memcached 天生支持集群 redis 简介.安装.使用.实例 Python 操作 Redis String.Hash.Li ...

  8. 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)

    Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...

  9. windows下 安装 rabbitMQ 及操作常用命令

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.它遵循Mozilla Public License开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器,Rab ...

随机推荐

  1. BZOJ4657 : tower

    显然只有横向和纵向的两个炮塔才有可能冲突. 考虑最小割,将每个炮塔所有能攻击到的位置建点,相邻之间连无穷的边,表示前缀和关系,即选了一个点,就必须要选所有比它近的点. 属于横向炮塔的点向$S$连边,容 ...

  2. Java 动态代理

    被代理的接口特点: 1. 不能有重复的接口,以避免动态代理类代码生成时的编译错误. 2. 这些接口对于类装载器必须可见,否则类装载器将无法链接它们,将会导致类定义失败. 3. 需被代理的所有非 pub ...

  3. 使用Adobe Edge Inspect在各种设备中轻松测试同一页面

    有过移动网站开发经历的开发者都知道,在各种设备中测试同一页面是一项非常繁琐的工作.现在,我们可以使用Adobe Edge Inspect来简化这一工作.如果使用Edge Inspect,可以在各种设备 ...

  4. Android MultiDex

    出现的原因: 当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt.DexOpt的执行过程是在第一次加载Dex文件的时候执行的.这个过程会生 ...

  5. insert into select 与select into from -- sql 批量插入

    参考资料:http://www.w3school.com.cn/sql/sql_union.asp   UNION:操作符用于合并两个或多个select语句的结果集.                 ...

  6. HDU-3549 最大流模板题

    1.HDU-3549   Flow Problem 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=3549 3.总结:模板题,参考了 http://ww ...

  7. 腾讯云Linux系统中启动自己安装的tomcat

    腾讯云Linux系统中启动自己安装的tomcat 首先通过工具查看一下安装的tomcat的位置 进入命令行之后输入以下指令: 此时,tomcat已经启动了.

  8. Eclipse 使用maven创建Dynamic Web Project

    今天看到spring的官网首页已经没有下载连接了,建议使用maven构建spring项目.虽然maven已经不是新技术,但是这个我还没用过,谷歌走起! 通常创建项目都是用Eclipse,前几年还是My ...

  9. C# 非模式窗体show()和模式窗体showdialog()的区别(转)

    对话框不是模式就是无模式的.模式对话框,在可以继续操作应用程序的其他部分之前,必须被关闭(隐藏或卸载).例如,如果一个对话框,在可以切换到其它窗 体或对话框之前要求先单击“确定”或“取消”,则它就是模 ...

  10. 【Go语言】错误与异常处理机制

    ①error接口 Go语言中的error类型实际上是抽象了Error()方法的error接口 type error interface { Error() string } Go语言使用该接口进行标准 ...