gpt4 book ai didi

Erlang 动态主管启动 gen_server

转载 作者:行者123 更新时间:2023-12-01 07:46:27 27 4
gpt4 key购买 nike

我有创建其他主管的根主管:

start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
RestartStrategy = {one_for_one, 5, 600},
ListenerSup =
{popd_listener_sup,
{popd_listener_sup, start_link, []},
permanent, 2000, supervisor, [popd_listener]},

Children = [ListenerSup],

{ok, {RestartStrategy, Children}}.

我有 gen_server - 听众。创建主管后,如何使用 popd_listener_sup 主管运行此 gen_server?

谢谢你。

最佳答案

根主管

-module(root_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1, shutdown/0]).

start_link() ->
supervisor:start_link({local,?MODULE}, ?MODULE, []).

init(_Args) ->
RestartStrategy = {one_for_one, 10, 60},
ListenerSup = {popd_listener_sup,
{popd_listener_sup, start_link, []},
permanent, infinity, supervisor, [popd_listener_sup]},
Children = [ListenerSup],
{ok, {RestartStrategy, Children}}.

% supervisor can be shutdown by calling exit(SupPid,shutdown)
% or, if it's linked to its parent, by parent calling exit/1.
shutdown() ->
exit(whereis(?MODULE), shutdown).
% or
% exit(normal).

如果子进程是另一个监督者,那么子规范中的 Shutdown 应该设置为 infinity 以给子树足够的时间关闭,并且 Type 应该设置为 supervisor ,这就是我们所做的。

child 监督员
-module(popd_listener_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).

start_link() ->
supervisor:start_link({local,?MODULE}, ?MODULE, []).

init(_Args) ->
RestartStrategy = {one_for_one, 10, 60},
Listener = {ch1, {ch1, start_link, []},
permanent, 2000, worker, [ch1]},
Children = [Listener],
{ok, {RestartStrategy, Children}}.

这里,在子规范中,我们将 Shutdown 的值设置为 2000 。整数超时值意味着主管将通过调用 exit(Child,shutdown) 告诉子进程终止,然后等待退出信号,原因是从子进程关闭。

听众
-module(ch1).
-behaviour(gen_server).

% Callback functions which should be exported
-export([init/1]).
-export([handle_cast/2, terminate/2]).

% user-defined interface functions
-export([start_link/0]).

start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

init(_Args) ->
erlang:process_flag(trap_exit, true),
io:format("ch1 has started (~w)~n", [self()]),
% If the initialization is successful, the function
% should return {ok,State}, {ok,State,Timeout} ..
{ok, []}.

handle_cast(calc, State) ->
io:format("result 2+2=4~n"),
{noreply, State};
handle_cast(calcbad, State) ->
io:format("result 1/0~n"),
1 / 0,
{noreply, State}.

terminate(_Reason, _State) ->
io:format("ch1: terminating.~n"),
ok.

来自 Erlang/OTP 文档:

If the gen_server is part of a supervision tree and is ordered by its supervisor to terminate, the function Module:terminate(Reason, State) will be called with Reason=shutdown if the following conditions apply:

  • the gen_server has been set to trap exit signals, and
  • the shutdown strategy as defined in the supervisor's child specification
    is an integer timeout value, not
    brutal_kill.


这就是我们在 erlang:process_flag(trap_exit, true) 中调用 Module:init(Args) 的原因。

sample 运行

启动根主管:
1> root_sup:start_link().
ch1 has started (<0.35.0>)
{ok,<0.33.0>}

根主管运行并自动启动它的子进程,在我们的例子中是子主管。子主管依次启动其子进程;在我们的例子中,我们只有一个 child , ch1

让我们让 ch1 评估正常代码:
2> gen_server:cast(ch1, calc).
result 2+2=4
ok

现在一些不好的代码:
3> gen_server:cast(ch1, calcbad).
result 1/0
ok
ch1: terminating.

=ERROR REPORT==== 31-Jan-2011::01:38:44 ===
** Generic server ch1 terminating
** Last message in was {'$gen_cast',calcbad}
** When Server state == []
** Reason for termination ==
** {badarith,[{ch1,handle_cast,2},
{gen_server,handle_msg,5},
{proc_lib,init_p_do_apply,3}]}
ch1 has started (<0.39.0>)
4> exit(normal).
ch1: terminating.
** exception exit: normal

如您所见,子进程 ch1 被子主管 popd_listener_sup 重新启动(注意 ch1 has started (<0.39.0>) )。

由于我们的 shell 和 root supervisor 是双向链接的(在 root supervisor 函数 supervisor:start_link 中调用 supervisor:start ,而不是 start_link/0 ), exit(normal) 导致 root supervisor 关闭,但它的子进程有一些时间来清理。

关于Erlang 动态主管启动 gen_server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4842871/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com