zoukankan      html  css  js  c++  java
  • a simple erlang process pool analysis

    a simple erlang process pool analysis

    这是一个简单的erlang进程池分析,是learn you some erlang for Great Good 里面的一个example,具体的内容可到官网查看!

    基本的流程图

     ppool flower

    实现原理

    这个的样例的实现原理官网都有比較具体的说明,主要模块在ppool_serv中,ppool_serv是一个gen_server behaviour, 而ppool_sup 是一个one_for_all的策略,假设ppool_serv或者worker_sup出现故障,彼此也没有存在的必要了。

    这里ppool_serv 和 worker_sup的实现,使用了一个简单的技巧,由于worker_sup不是ppool_sup直接调用生成的,它是由ppool_serv控制生成的:

    %% Gen server
    init({Limit, MFA, Sup}) ->
        %% We need to find the Pid of the worker supervisor from here,
        %% but alas, this would be calling the supervisor while it waits for us!
        self() ! {start_worker_supervisor, Sup, MFA},
        {ok, #state{limit=Limit, refs=gb_sets:empty()}}.
    

    woker_supppool_serv自己在init函数中,发给自己一个Message,然后在回调函数中才生成:

    handle_info({start_worker_supervisor, Sup, MFA}, S = #state{}) ->
        {ok, Pid} = supervisor:start_child(Sup, ?SPEC(MFA)),
        link(Pid),
        {noreply, S#state{sup=Pid}};
    

    假设他们一起直接生产,那么会产生死锁,

    当然,他这里的生成顺序,能够自己改动一下,也不会出现死锁。


    gen_serv的主要数据结构

    -define(SPEC(MFA),
            {worker_sup,
             {ppool_worker_sup, start_link, [MFA]},
              temporary,
              10000,
              supervisor,
              [ppool_worker_sup]}).
    
    -record(state, {limit=0,
                    sup,
                    refs,
                    queue=queue:new()}).
    

    ?SPEC(MFA), 这里的MFA指明一类Task,所以同一个ppool_worker_sup,不会有不同类型的Task,它的策略也是simple_one_for_one.

    在这个样例中,使用了一个gen_server -- nnager module 作为Task,这个Task的參数为:{Task, Delay, Max, SendTo}, Task标示任务名字,Delay作为超时时间,仅仅是标示这个任务是有超时限制的,也是一个调试技巧,Max为最大超时次数,SendTo用来发送信息给回调进程,这个进程能够是shell, 假设是shell,flush()就会收到信息。

    record 用来标识一些基本的信息,Limit为进程池的限制大小,sup開始为ppool_sup的pid(),在生成woker_sup进程后,就变成worker_sup的进程pid(),由于ppool_serv的主要交流对象还是worker_sup和worker(Task); refs(gb_set)为woker的进程链接,这样能够在worker进程down掉或者done时,从线程池中剔除掉;queue为任务队列,当任务大于limit时,就把多余的任务放到queque中,等到进程池有空暇时,就从中pop出任务,接着处理。

    这里有些局限的地方:1.每次的任务都是新建的进程去处理,就是说进程的生命周期跟任务的生命周期是一样的,能够把进程跟任务分离出来,让进程不随任务的结束而结束(当然这的任务就不要是gen_server,gen_fsm这些,由于这些也是spawn出来的进程),这样进程开销理论上一次初始化即可了,尽管进程在erlang中开销比較少;2.队列没有限制大小

  • 相关阅读:
    程序的编码问题
    man DMIDECODE
    Github熟悉一
    man uname
    第一轮铁大树洞APP开发冲刺(2)
    第九周学习进度
    第九周安卓开发学习总结(3)
    第一轮铁大树洞APP开发冲刺(1)
    第九周安卓开发学习总结(2)
    第九周安卓开发学习总结(1)
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4171448.html
Copyright © 2011-2022 走看看