【问题标题】:How to run a supervisor with workers which are not gen_servers?如何与不是 gen_servers 的工作人员一起运行主管?
【发布时间】:2020-07-17 18:26:36
【问题描述】:

您好,我正在尝试运行 supervisor,其工作人员不是 gen_server(s)。 为简洁起见,我的主管与工人在同一模块中定义:

我不断收到此错误,我尝试将MFA 属性放入[ ] 无济于事。我还将ChildSpec 放入[ ]。 我错过了什么?

我不希望我的主管在启动它时有任何工人。

错误

>  X=sup:start_link().
> ** exception error: no match of right hand side value {error,
>                                                        {bad_start_spec,[]}}
>      in function  sup:start_link/0 (c:/Erlang/ProcessPool/sup.erl, line 6)
> =CRASH REPORT==== 5-Apr-2020::22:20:32.918000 ===   crasher:
>     initial call: supervisor:sup/1
>     pid: <0.280.0>
>     registered_name: []
>     exception exit: {bad_start_spec,[]}
>       in function  gen_server:init_it/6 (gen_server.erl, line 358)
>     ancestors: [<0.273.0>]
>     message_queue_len: 0
>     messages: []
>     links: [<0.273.0>]
>     dictionary: []
>     trap_exit: true
>     status: running
>     heap_size: 376
>     stack_size: 27
>     reductions: 205   neighbours:

模块

-module(sup).
-behaviour(supervisor).
-compile([export_all]).

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

init(_Args) ->
     RestartStrategy = {simple_one_for_one, 10, 60},
    {ok, {RestartStrategy,[]}}.

add(Sup,Value)->                #adding child
    ChildSpec = {
                  ch1, 
                  {sup, start, [Value]},
                  permanent,
                  brutal_kill, 
                  worker, 
                  [ch1]
                },
    supervisor:start_child(Sup,ChildSpec).


start([Value])->                                    #child's start_link equivalent (non-genserver)
    spawn_link(?MODULE,initworker,[self(),Value]).

initworker(From,Value)->                            #child's init
    receive 
       MSG->From ! {got_msg,Value,MSG}
    end.

【问题讨论】:

    标签: erlang erlang-supervisor


    【解决方案1】:

    当您使用simple_one_for_one 时,您应该在init 中定义ChildSpec,并且所有孩子都使用相同的ChildSpec

    如果您需要不同,请改用“one_for_one”策略。

    对于simple_one_for_one

    supervisor:start_child/2 的第二个参数必须是一个列表,该列表将与ChildSpec 中定义的子启动函数参数的默认参数组合。

    在这里,我快速修改了代码以使其适合您。

    -module(sup).
    -behaviour(supervisor).
    -compile([export_all]).
    
    start_link() ->
         {ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
         Pid.
    
    init(_Args) ->
         RestartStrategy = {simple_one_for_one, 10, 60},
         ChildSpec = {
                      ch1, 
                      {sup, start, []},
                      permanent,
                      brutal_kill, 
                      worker,
                      [sup]
                    },
        {ok, {RestartStrategy,[ChildSpec]}}.
    
    add(Sup,Value)->                
        supervisor:start_child(Sup,[Value]).
    
    
    start(Value)->                                    
        P = spawn(?MODULE, initworker,[]),
        P!{self(),Value},
        {ok,P}.
    
    initworker()->                            
        receive 
           {From, MSG} -> io:format(" Value is ~p~n", [MSG])
        end.
    

    【讨论】:

    • 我不明白。ChildSpec不能加在init后面吗?我的意思是当我使用supervisor:start_child 时,我不能设置它的子规范吗?在添加任何子之前,主管是否需要知道规范?
    • 用不同的代码开始一个孩子是违反“simple_one_for_one”主管的工作方式的。请在此处查看文档erlang.org/doc/man/supervisor.html#check_childspecs-1。正如我的回答中所述,您可以尝试“一对一”主管在“初始化”之后拥有 ChildSpec。更多信息:stackoverflow.com/questions/11120207/…stackoverflow.com/questions/41190705/…
    • 好的,但是有没有办法将我的ChildSpec 的数据注入到之后生成的每个孩子体内?在我的示例中,id 喜欢在 init()MFA 中添加一些参数,这些参数将传递给所有添加的子项。
    • 如果你在初始化之后需要 ChildSpec。修改代码以像这样使用 one_for_one。如果您调用 sup:add(sup:start_link(),"newargument"),答案中的codepile.net/pile/0zeJrpow 或以上代码也可以动态添加参数。
    猜你喜欢
    • 2016-06-17
    • 2020-12-10
    • 1970-01-01
    • 2020-12-19
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    相关资源
    最近更新 更多