有时候我们原先设计了一套系统,可是并没有按照otp的标准来实现,可是我们又想使用otp进程树的形式对其进行监督和管理时,
这种情况下,我们就可以使用supervisor_bridge进行桥接。
如果我们想将进程纳入进树的管理,一般来说,无非是实现gen_server, gen_event, gen_fsm等behaviour,然后用supervisor模块进行管理。
所以supervisor_bridge本质上是一个实现了gen_server behaviour的模块,作为一个子系统进程的容器,定义了两个回调函数。
init/1:supervisor_bridge进程初始化时,对子系统的回调。
terminate/2:supervisor_bridge进程终止时候,对子系统的回调。
我们在使用时,实际是将该模块纳入到supervisor的管理下,方便的对其进行各种管理。
supervisor_bridge 初始化时,link到接入的子系统的进程,当子系统进程结束时候,同时结束自身实现了gen_server的进程,这也实现和子系统进程和进程树的交互。
接下来我举个例子,比如我们有一个sub_system模块:
-module(sub_system). -export([start/0]). -record(state, {msg}). start() -> register(sub_system, spawn(fun() -> loop(#state{msg = 0}) end)). loop(State = #state{msg = Msg}) -> receive Msg -> loop(State#state{msg = Msg + 1}) end.
这时候,我们想要用supervisor对其进行管理,只需要实现supervisor_bridge模块,如下:
-module(sub_system). -behaviour(supervisor_bridge). -export([start/0]). -export([init/1, terminate/2]). -record(state, {msg}). init([]) -> Pid = spawn(fun() -> loop(#state{msg = 0}) end), {ok, Pid, []}. terminate(_Reason, _State) -> ok. %% ================================================== start() -> supervisor_bridge:start_link({local, sub_system}, sub_system, []). loop(State = #state{msg = Msg}) -> receive Msg -> loop(State#state{msg = Msg + 1}) end.
同时我们在supervisor里,注册这样的Spec:
SubSystem = {sub_system, {sub_system, start, []},
permanent, 5000, supervisor, [sub_system]},
这样,我们实际生成了一个注册名为sub_system的进程,这个进程作为容器,直接链接到真正子系统进程,我们就可以
通过sub_system进程进行桥接,挂接到进程树上,对子系统进程进行重启,关闭,添加,删除等进程管理。