简体   繁体   English

Erlang:在主管的领导下进行多个流程

[英]Erlang: Spawn more than one process under a supervisor

I'm trying implement a simple supervisor and just have it restart child processes if they fail. 我正在尝试实现一个简单的主管,并让它在失败时重新启动子进程。 But, I don't even know how to spawn more than one process under a supervisor! 但是,我什至不知道如何在主管下生成多个进程! I looked at simple supervisor code on this site and found something 我在这个网站上查看了简单的主管代码,发现了一些东西

-module(echo_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).

start_link() ->
    {ok, Pid} = supervisor:start_link(echo_sup, []),
    unlink(Pid).
init(_Args) ->
    {ok,  {{one_for_one, 5, 60},
       [{echo_server, {echo_server, start_link, []},
         permanent, brutal_kill, worker, [echo_server]},

        {echo_server2, {echo_server2, start_link, []},
         permanent, brutal_kill, worker, [echo_server2]}]}}.

I assumed that putting "echo_server2" part in the init() function would spawn another process under this supervisor, but I end up getting an exception exit:shutdown message. 我以为将“ echo_server2”部分放在init()函数中将在此管理程序下生成另一个进程,但最终导致出现异常exit:shutdown消息。

Both the files "echo_server" and "echo_server2" are the same code but different names. 文件“ echo_server”和“ echo_server2”都是相同的代码,但名称不同。 So I'm just confused now. 所以我现在很困惑。

-module(echo_server2).
-behaviour(gen_server).

-export([start_link/0]).
-export([echo/1, crash/0]).
-export([init/1, handle_call/3, handle_cast/2]).

start_link() ->
    {ok,Pid} = gen_server:start_link({local, echo_server2}, echo_server2, [], []),
    unlink(Pid).

%% public api
echo(Text) ->
    gen_server:call(echo_server2, {echo, Text}).
crash() ->
    gen_server:call(echo_server2, crash).

%% behaviours
init(_Args) ->
    {ok, none}.
handle_call(crash, _From, State) ->
    X=1,
    {reply, X=2, State};
handle_call({echo, Text}, _From, State) ->
    {reply, Text, State}.
handle_cast(_, State) ->
    {noreply, State}.

First you need read some docs about OTP/gen_server and OTP/supervisors. 首先,您需要阅读一些有关OTP / gen_server和OTP / supervisor的文档。 You have few errors in your code. 您的代码中几乎没有错误。

1) In echo_sup module change your start_link function as follow: 1)在echo_sup模块中,如下更改您的start_link函数:

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

Dont know why do you unlink/1 after process has been started. 不知道您为什么在过程开始后就unlink/1

2) In both echo_servers change start_link function to: 2)在两个echo_servers中,将start_link函数更改为:

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

You should not to change return value of this function, because supervisor expect one of this values: 您不应该更改此函数的返回值,因为主管期望以下值之一:

{ok,Pid} | ignore | {error,Error}

You don't need two different modules just to run two instances of the same server. 您不需要两个不同的模块即可运行同一服务器的两个实例。 The conflict problem is due to the tag in the child specification which has to be unique. 冲突问题是由于子规范中的标签必须唯一。 It is the first element in the tuple. 它是元组中的第一个元素。 So you could have something like: 因此,您可能会遇到以下情况:

    [{echo_server, {echo_server, start_link, []},
      permanent, brutal_kill, worker, [echo_server]},
     {echo_server2, {echo_server, start_link, []},
      permanent, brutal_kill, worker, [echo_server]}]}}.

Why do you unlink the child processes? 为什么取消链接子进程? The supervisor uses these links to supervise its children. 监督者使用这些链接来监督其孩子。 The error you are getting is that the supervisor expects the functions which start the children to return {ok,ChildPid} , this is how it gets the pid of the children, so when it gets another return value it fails the startup of the children and then gives up itself. 您得到的错误是,主管希望启动子项的函数返回{ok,ChildPid} ,这就是它获取子项的pid的方式,因此当它获得另一个返回值时,将无法启动子项,并且然后放弃自己。 All according to how it is supposed to work. 一切都取决于它应该如何工作。

If you want to register both servers then you could modify the start_link function to take the name to use as an argument and pass so you can explicitly pass it in through the child spec. 如果要注册两个服务器,则可以修改start_link函数,以将名称用作参数并传递,以便您可以通过子规范将其显式传递。 So: 所以:

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

and

    [{echo_server, {echo_server, start_link, [echo_server]},
      permanent, brutal_kill, worker, [echo_server]},
     {echo_server2, {echo_server, start_link, [echo_server2]},
      permanent, brutal_kill, worker, [echo_server]}]}}.

Using the module name as the registered name for a server is just a convention which only works if you run one instance of the server. 使用模块名称作为服务器的注册名称只是一种约定,只有在您运行服务器的一个实例时才有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM