上一篇已经分析了rpool 的三个module , 以及简单的物理关系. 这次主要分析用户进程和 worker_pool 进程还有worker_pool_worker 进程之间的调用关系. 在开始之前, 必须先明确一点, 就是一个worker_pool_worker 进程只有在处理完一个用户进程的任务之后才能开始处理另一用户进程的任务.

worker_pool 状态管理

在上一篇已经说明, worker_pool 管理了rpool 工作进程的ready idle busy 状态,从worker_pool 的代码可以看出, 对于idle 状态和busy 状态的处理逻辑是相同的.

 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};

以上是submit 请求在 available queue 不为空时的处理逻辑.

 handle_cast({run_async, Fun}, State = #state { available = [WPid | Avail1] }) ->
worker_pool_worker:submit_async(WPid, Fun),
{noreply, State #state { available = Avail1 }, hibernate};

而以上是submit_async 请求在available queue 不为空时的处理逻辑.

 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};

当某工作进程完成对用户进程任务的处理之后, cast 给worker_pool 进程 idle 消息, worker_pool 会:

1, 判断pending 是否为空, 若空, 则将工作进程add 到available中;

2, 若pending 为 next_free, 则执行submit 请求时的处理流程;

3, 若pending 为run_async, 则执行submit_async 请求时的处理流程.

submit

用户进程在调用submit 请求时的基本流程如上图所示:

1, 用户进程call 请求 worker_pool 进程 next_free

2, worker_pool 进程 获取available 中的工作进程(PidA)并返回给用户进程

3, 用户进程call 请求PidA 工作进程submit

工作进程PidA 在ready 或 idle 时,工作进程的state 信息就会被置为undefined .

也就是在first message 到达工作进程时, 工作进程的state 信息为undefined, 那么工作进程处理上图first message 的逻辑为:

 handle_cast({next_job_from, CPid}, undefined) ->
MRef = erlang:monitor(process, CPid),
{noreply, {from, CPid, MRef}, hibernate};

也就是 monitor 用户进程UPA, 并将自身的state 重置为 {from, CPid, MRef}, 然后等待UPA 进程的submit 请求, 也就是second message .

如果在这中间, UPA 异常退出, 工作进程就会收到{'DOWN' ... } message:

 handle_info({'DOWN', MRef, process, CPid, _Reason}, {from, CPid, MRef}) ->
ok = worker_pool:idle(self()),
{noreply, undefined, hibernate};

然后将state 重置为undefined .

submit_async

用户进程在调用submit_async 请求时的基本流程如上图所示:

1, 用户进程cast 请求worker_pool 进程 run_async 参数是需要execute Fun

2, worker_pool 进程获取available 中的工作进程(PidA)并 cast submit_async 请求给PidA 参数为PidA 和 Fun

3, 然后进程在handle_cast callback 中进行处理.

 handle_cast({submit_async, Fun}, undefined) ->
run(Fun),
ok = worker_pool:idle(self()),
{noreply, undefined, hibernate};

和submit 操作相比, 工作进程在处理submit_async 请求时,不需要monitor 用户进程(UPA), 不需要将Fun execute 执行的结果返回用户进程.

总结

在Mac 下omnigraffle 真的挺好用的,就是太贵了. :(

Erlang pool management -- RabbitMQ worker_pool 2的更多相关文章

  1. Erlang pool management -- RabbitMQ worker_pool

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

  2. Erlang pool management -- Emysql pool optimize

    在上一篇关于Emysql pool (http://www.cnblogs.com/--00/p/4281938.html)的分析的最后提到 现在的emysql_conn_mgr gen_server ...

  3. Erlang pool management -- Emysql pool

    从这篇开始,这一系列主要分析在开源社区中,Erlang 相关pool 的管理和使用. 在开源社区,Emysql 是Erlang 较为受欢迎的一个MySQL 驱动. Emysql 对pool 的管理和使 ...

  4. Ubuntu16.04下,erlang安装和rabbitmq安装步骤

    文章来源: Ubuntu16.04下,erlang安装和rabbitmq安装步骤 准备工作,先下载erlang和rabbitmq的安装包,注意他们的版本,版本不对可能会导致rabbitmq无法启动,这 ...

  5. 使用kombu的producer pool 向rabbitmq瞬间发送大量消息

    kombu比pika感觉考虑得全面多了,不知道为什么用的人好像少? 生产端是 python-socket.io 的client   接受socketio 消息后, 发到rabbitmq 按时序进行处理 ...

  6. erlang pool模块。

    出自: http://blog.sina.com.cn/s/blog_96b8a154010168ti.html

  7. Erlang及Rabbitmq安装

    1. 下载erlang源代码及RabbitMQ rpm安装包      $ wget http://www.erlang.org/download/otp_src_R16B02.tar.gz $ wg ...

  8. linux centos7 erlang rabbitmq安装

    最终的安装目录为/opt/erlang 和 /opt/rabbitmq wget http://erlang.org/download/otp_src_21.0.tar.gztar zxvf otp_ ...

  9. centos6.5 以 zero-dependency Erlang from RabbitMQ 搭建环境

    rabbitmq 官方安装文档可参考:http://www.rabbitmq.com/install-rpm.html  ,由于rabbitmq 使用Erlang 开发的,运行环境需要用到Erlang ...

随机推荐

  1. Python多线程循环

    背景:Python脚本:读取文件中每行,放入列表中:循环读取列表中的每个元素,并做处理操作. 核心:多线程处理单个for循环函数调用 模块:threading 第一部分:   :多线程脚本 (该脚本只 ...

  2. JAVA获取webapp路径

    1.使用ServletContext获取webapp目录 在Servlet中 String path = getServletContext().getRealPath("/"); ...

  3. JavaScript -- 广告随鼠标移动, 点击一次后关闭

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. CSDN_博客__WapPc

    CSDN 博客  手机上的网址 和 PC上的网址,对应关系: 1. 举个例子: 手机上的网址: http://m.blog.csdn.net/article/details?id=7910239 PC ...

  5. ZC_知识点

    1. 在创建一个JNI动态库的工程时应该将工程的输出目标设置为动态连接库(Windows下为.dll,Unix-like系统下为.so,OS X下为.dylib) 2.类型对应关系 (Java与C/C ...

  6. SSIS包的组建之连接管理器

    上一篇我们通过一个示例来介绍一下SSIS 包的开发.接下来的内容我们将学习一下包中各个选项卡的使用.如:连接管理器选项卡.控制流选项卡.数据流选项卡和事件处理选项卡等等.这一篇将介绍一下连接管理器作用 ...

  7. Windows 10 SDK 10.0.10158

    昨天微软发布了Windows 10 SDK 10158版本: http://blogs.windows.com/buildingapps/2015/06/30/windows-10-sdk-previ ...

  8. linux设置开机自动进入命令模式

    1)打开终端,输入命令:      su – root     2)输入密码 3)再输入如下命令进入到命令行模式:      init 3 4)修改启动模式为永久命令行模式:      vi /etc ...

  9. ural 2012 About Grisha N.(水)

    2012. About Grisha N. Time limit: 1.0 secondMemory limit: 64 MB Grisha N. told his two teammates tha ...

  10. nyojb 2357

    http://acm.nyist.me/JudgeOnline/problem.php?id=2357 2357: 插塔憋憋乐 时间限制: 1 Sec  内存限制: 128 MB提交: 50  解决: ...