Erlang 构建多层监督机制
2015-12-17 03:08
260 查看
今天在写项目时需要用到 Erlang 的多层监督机制,写过程中遇到点问题,再此记录下来,也希望对正在学习 Erlang 的小伙伴有帮助。
Erlang 支持多重监督机制。otp design 上面有详细的介绍。
大致样子如下图:
途中方块表示督程(supervisor),圆圈表示拥程(worker)。本篇文章从头到尾会建立一个上图所示的监督树。
开始我们先用 rebar 简单的建立个项目
名称为 one,这也就是说我们最顶层的督程为 one_sup。
建立完成后会产生一下 3 个文件:
one_app.erl
one.app.src
one_sup.erl
先放这里:)
注意:
这句代码指定了督程的名字为
如果你是通过
子拥程
我们来一步一步运行并通过
首先,要通过
此时监督树如下图所示:
进程状态图:
现在,我们来给
监督树如下图:
到这里基本就完成了,读者可以自行尝试下给
比如:
什么情况下用 simple_one_for_one?
督程是否需要命名,拥程呢,什么情况下需要命名?
上图中监督树的第二层拥程可否动态扩展,督程呢,哪个是真正有必要扩展?
以上问题欢迎讨论:)
本文源代码戳 这里
Erlang 支持多重监督机制。otp design 上面有详细的介绍。
大致样子如下图:
途中方块表示督程(supervisor),圆圈表示拥程(worker)。本篇文章从头到尾会建立一个上图所示的监督树。
开始我们先用 rebar 简单的建立个项目
[code]rebar create-app appid=one
名称为 one,这也就是说我们最顶层的督程为 one_sup。
建立完成后会产生一下 3 个文件:
one_app.erl
one.app.src
one_sup.erl
先放这里:)
建立督程 one_sup:
one_sup.erl文件如下,使用
rebar建立会有默认模板,为代码的简洁性我就去掉了:)
[code]-module(one_sup). -behaviour(supervisor). -export([start_link/0]). -export([init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> {ok, { {one_for_one, 5, 10}, [ %% 子督程 {son_sup, {son_sup, start_link, []}, temporary, brutal_kill, supervisor, [son_sup] }, %% 子拥程 {son_work, {son_work, start_link, []}, temporary, brutal_kill, worker, [son_work] } %% 子拥程2 {son_work2, {son_work, start_link, []}, temporary, brutal_kill, worker, [son_work] } ] } }.
start_link会创建一个
supervisor督程,创建后
init函数将被调用。
init函数指定了督程两种子进程的类型,一种为
supervisor,另一种为
worker。
init函数内部剩余参数如果不理解戳 Erlang otp Supervisor 行为 。
注意:
[code]start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
这句代码指定了督程的名字为
?MODULE模块名,我们只有在确定某个进程唯一时(也就是确保
start_link只被调用一次时)才能注册名字。否则第二次添加进程会报错 进程已存在。
建立子督程 son_sup:
[code]-module(son_sup). -behaviour(supervisor). -export([start_link/0]). -export([init/1]). start_link() -> supervisor:start_link(?MODULE, []). init([]) -> {ok, { {simple_one_for_one, 5, 10}, [ { grandson_work, {grandson_work, start_link, []}, temporary, brutal_kill, worker, [grandson_work] } ] } }.
start_link函数建立子督程,并指定该督程的子进程是
worker拥程。
simple_one_for_one表明我们必须手动添加(通过
start_child)该进程的子进程。
建立子拥程 son_work:
[code]-module(son_work). -behaviour(gen_server). -define(SERVER, ?MODULE). -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). start_link() -> io:format("我是子拥程~p~n", [self()]), gen_server:start_link(?MODULE, [], []). init(Args) -> {ok, Args}. handle_call(_Request, _From, State) -> {reply, ok, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}.
如果你是通过
rebar构建项目的话,这里的代码命令就可生成。
rebar create template=simplesrv srvid=son_work
子拥程
son_work是一个
gen_server。
建立子督程的拥程 grandson_work:
都是worker,代码结构与上面大致相同。
[code]-module(grandson_work). -behaviour(gen_server). -define(SERVER, ?MODULE). -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). start_link() -> gen_server:start_link(?MODULE, [], []). init(Args) -> {ok, Args}. handle_call(_Request, _From, State) -> {reply, ok, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}.
运行观察:
代码分布如下图:我们来一步一步运行并通过
observer来观察。
首先,要通过
observer观察结构图必须构建一个应用
application,因为
observer上只能观察应用的进程结构图。
此时监督树如下图所示:
<0.38.0>和
<0.39.0>是应用
application_master创建。
进程状态图:
现在,我们来给
<0.41.0>子督程添加拥程。
监督树如下图:
到这里基本就完成了,读者可以自行尝试下给
son_sup再添加一个拥程。就完全如同开篇图片的样子。
总结:
监督机制是 Erlang 的一个重大特性,在细节方面还需要注意一些问题。比如:
什么情况下用 simple_one_for_one?
督程是否需要命名,拥程呢,什么情况下需要命名?
上图中监督树的第二层拥程可否动态扩展,督程呢,哪个是真正有必要扩展?
以上问题欢迎讨论:)
本文源代码戳 这里
相关文章推荐
- 安卓学习笔记五
- leetcode - Palindrome Number
- MUI 个推
- win32记事本程序(二)
- Linux netstat命令详解
- Linux netstat命令详解
- leetcode - StringtoInteger
- #3JAVA面向对象之继承#
- QP-nano结构分析
- 瞄了一眼墙外的世界,只能给差评
- sgu194 Reactor Cooling【无源汇有上下界可行流】
- SolrCloud原理
- Sicily 1003. Hit or Miss
- [Javascript] Advanced Reduce: Flatten, Flatmap and ReduceRight
- Name Mangling and Function Overloading
- [蓝牙] 6、基于nRF51822的蓝牙心率计工程消息流Log分析(详细)
- OpenGL超级宝典7th简体中文-第一章:简介
- 第四次Scrum meeting
- 【jQuery】:selected选中状态选择器
- c语言:2种方法:5位运动员参加跳水比赛,每位选手都说对一半,请确定比赛名次