构建监控树
现在回到之前的方法中并构建一个监控树。
先给这个监控器选一个名字,名为
sellaprime
。
sellaprime
监控器的工作是确保质数和面积服务器始终保持运行。为了做到这一点,就得编写另一个用于gen_supervisor的回调模块。这个模块的代码如下:
-module(sellaprime_supervisor).
%%%=======================EXPORT=======================
-export([start/0, start_in_shell_for_testing/0, start_link/1, init/1]).
%%%=======================INCLUDE======================
-behaviour(supervisor).
%%%=======================RECORD=======================
%%%=======================DEFINE=======================
%%%=======================TYPE=========================
%%%=================EXPORTED FUNCTIONS=================
%% ----------------------------------------------------
%% Description:
%% ----------------------------------------------------
start() ->
spawn(fun() -> supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = []) end).
start_in_shell_for_testing() ->
{ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = []),
unlink(Pid).
start_link(Args) ->
supervisor:start_link({local, ?MODULE}, ?MODULE, Args).
init([]) ->
%% 安装自己的错误处理器
gen_event:swap_handler(alarm_handler, {alarm_handler, swap}, {my_alarm_handler, xyz}),
{ok, {{one_for_one, 3, 10},
[{tag1,
{area_server, start_link, []},
permanent,
10000,
worker,
[area_server]},
{tag2,
{prime_server, start_link, []},
permanent,
10000,
worker,
[prime_server]}
]}}.
%%%===================LOCAL FUNCTIONS==================
%% ----------------------------------------------------
%% Description:
%% ----------------------------------------------------
重点部分是init/1返回的数据结构:
init([]) ->
%% 安装自己的错误处理器
gen_event:swap_handler(alarm_handler, {alarm_handler, swap}, {my_alarm_handler, xyz}),
{ok, {{one_for_one, 3, 10},
[{tag1,
{area_server, start_link, []},
permanent,
10000,
worker,
[area_server]},
{tag2,
{prime_server, start_link, []},
permanent,
10000,
worker,
[prime_server]}
]}}.
这个数据结构定义了一种监控策略。之前讨论过监控策略和重启频率,现在剩下的就是面积
服务器和质数服务器的启动格式了。
Worker
的格式是下面这种元组:
{Tag, %%这是一个原子类型的标签,将来可以用它指代工作进程(如果有必要的话)。
{Mod, Func, ArgList}, %%它定义了监控器用于启动工作器的函数,将被用作apply(Mod, Fun, ArgList)的参数。
Restart, %%Restart = permanent | transient | temporary,permanent(永久)进程总是会被重启。transient(过渡)进程只有在以非正常退出值终止时才会被重启。temporary(临时)进程不会被重启。
Shutdown, %%这是关闭时间,也就是工作器终止过程允许耗费的最长时间。如果超过这个时间,工作进程就会被杀掉。
Type, %%这是被监控进程的类型。可以用监控进程代替工作进程来构建一个由监控器组成的树。
[Mod1] %%如果子进程是监控器或者gen_server行为的回调模块,就在这里指定回调模块名。
}
启动系统
首先来启动系统:
现在生成一个有效查询:
现在生成一个无效查询:
虽然面积服务器发生了崩溃,但之后一切都恢复正常,就像构想的那样。接下来生成一个合法请求:
系统又能正常工作了。现在来生成一个小质数:
再生成一个大质数:
现在就有了一个能正常运行的系统。如果某个服务器崩溃了,就会被自动重启,错误日志
里则会有关于这个错误的信息。