Erlang的supervisor

万事皆有因

这件事情的开始是很是加单的,我想把几个模块独立化,变的能够重复使用。而后就建立了几个application,可是将几个模块整合到同一个项目的时候,犯了一个小小的错误,这个错误虽然不是很致命,可是是一个很是很差的。app


产生缘由

一开始,我有一个主干项目A,建立了SupervisorA。以后我建立了一个项目B,同时建立了一个SupervisorB。而后将两个项目整合的时候,我项目B中的模块X的start_link的代码以下面这样
spa

-module(mod_x).
-export([start_link/1]).
start_link(opts)->
 Child = {mod_y,{mod_y,start_link,[]},permanent,5000,worker,[mod_y],
 supervisor:start_child(supervisor_b,Child).

而后我在主干项目中的SupervisorA的代码写成了这个样子code

-module(supervisor_a).
-export([start_link/0]).
-export([init/1]).
start_link() ->
  supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([])->
  RestartStrategy = {one_for_one, 5, 10},
  MFA = {mod_x,start_link,[]},
  Child = {mod_x,MFA,permanent,5000,worker,[mod_x]},
  {ok, { RestartStrategy,[Child]} }.

此时此刻我想你们已经看出问题了。server


解释下

这样执行下来,当打开observer会观察到mod_y的进程是和SupervisorB关联,而不是和SupervisorA关联。我先说下为何是和SupervisorB关联而不是和SupervisorA关联。而后再说下会有什么问题。进程

为何和SupervisorB关联。it

由于supervisor的start_child方法,是经过gen_server:call的方式,让指定的Supervisor经过start_link来建立child。而supervisor的start_link也是让指定的Supervisor经过mod:start_link来建立。换句话,就是supervisor并非使用monitor机制,而是使用trap_exit机制来监控它所建立的进程。io

那么会出现什么问题。class

若是mod_y这个进程,不当心死掉了,那么当咱们经过supervisor:which_children(SupervisorA)去寻找child的pid的时候,咱们是没法拿到正确的Pid。缘由就是上面那个,mod_y死掉后是SupervisorB负责重启的,而SupervisorA根本不知道这个变化。监控

相关文章
相关标签/搜索