標籤:style http ar io color os 使用 sp for
a simple erlang process pool analysis
這是一個簡單的erlang進程池分析,是learn you some erlang for Great Good 裡面的一個example,具體的內容可到官網查看!
基本的流程圖
實現原理
這個的範例的實現原理官網都有比較具體的說明,主要模組在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 serverinit({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_sup由ppool_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.隊列沒有限制大小
a simple erlang process pool analysis