开始和终止简单的孩子

我有一个简单的应用程序target_interceptor ,它在接收到注册和取消注册消息后,在simple_one_for_one rpc_server_supervisor下启动或终止工作。

主管rpc_server_supervisor的代码:

init([]) ->
    MaxRestart = 5,
    MaxTime = 3600,
    {ok, {{simple_one_for_one, MaxRestart, MaxTime},
            [{rbmq_rpc_server, 
                {rbmq_rpc_server, start_link, []},
                temporary,
                10000,
                worker,
                [rbmq_rpc_server]}]}}.

注册target_interceptor消息:

handle_cast({register, Args}, S = #state{channel = Channel, supervisor=Sup, refs=R, qs_link = QSLinks}) ->
    {Connection, QueueName, Node} = Args,   
    {Ok, Pid} = supervisor:start_child(Sup, [Connection, QueueName, Node]),
    Ref = erlang:monitor(process, Pid),
{noreply, S#state{refs=gb_sets:add(Ref,R), qs_link=orddict:append(binary_to_list(QueueName),Pid,QSLinks)}};

取消注册target_interceptor消息:

handle_cast({unregister,{QueueName}}, S = #state{supervisor = Sup, qs_link = QSLinks}) ->
    Pid = orddict:fetch(QueueName,QSLinks) 
    case supervisor:terminate_child(Sup,Pid) of
         ok -> Success = true;
         Error -> io:format("Error ~p~n",[Error]),
                  Success = false
    end,
{noreply, S#state{qs_link=orddict:erase(QueueName,QSLinks)}}

我的Erlang版本是:R15B01

第一个问题是处理注册操作时元组{OK,Pid} = {error,<0.57.0>}; 即使它指出出现了问题,Pid 57上的gen_server rbmq_rpc_server也能正常工作并对消息作出响应。 为什么start_child函数的返回值出错? 什么地方出了错?

第二个问题是处理注销操作时,即使我引用了Pid而非ChildID,supervisor:terminate_child(Sup,Pid)也会返回{error,simple_one_for_one)。 为什么它表现得像这样,我怎么能动态地和个别地终止我的主管的孩子?

编辑: target_interceptorrpc_server_supervisor都由rbmq_sup_sup监督员监督:

init({Nodeid, Node}) ->
    MaxRestart = 1,
    MaxTime = 3600,
    {ok, {{rest_for_one, MaxRestart, MaxTime},
            [{server,
                {target_interceptor, start_link, [target, self(), {Nodeid, Node}]},
                permanent,
                5000,
                worker,
                [target_interceptor]}]}}.

编辑:在target_interceptor的init()函数中调用rpc_server_supervisor(这里是Sup是rbmq_sup_sup管理器):

handle_info({start_worker_supervisor, Sup}, S = #state{}) ->
    {ok, Pid} = supervisor:start_child(Sup, ?SPEC),
    link(Pid),
    {noreply, S#state{sup=Pid}};

-define(SPEC,
        {rpc_server_sup,
            {rpc_server_sup, start_link, []},
            temporary,
            10000,
            supervisor,
            [rpc_server_sup]}).

随着时间的推移,我会补充一点。

第一点是{Ok,Pid}匹配任何元组甚至{error,Error}因此调用变量Ok可能不是最佳选择。

一个简单的问题:在handle_cast({register,Args}, ...你为key做了binary_to_list(QueueName) ,但是在handle_cast({unregister,{QueueName}}, ...你只是使用QueueName作为key。为什么你保留每个QueueName的pid列表,因为注销似乎清除了所有这些?这也意味着当你执行Pid = orddict:fetch(QueueName,QSLinks) Pid将是一个不是一个pid的列表。

rbmq_sup_sup你只能启动target_interceptor

rbmq_rpc_server进程是否已注册?

编辑:

我认为在unregister时出错的原因在于,您使用orddict:append/3保存了pid,即使第一次将值保存在列表中,而使用orddict:fetch/2值时orddict:fetch/2将返回整个列表在这种情况下。 所以Pid是一个列表。 然后你试着用Pid这个pid列表来杀死孩子,而不是pid这是supervisor:terminate_child/2正在抱怨的pid列表。

如果每个QueueName只有一个pid,则应该执行orddict:store(binary_to_list(QueueName), Pid, QSLinks) 。 然后orddict:fetch/2将返回pid。

PS orddict:append/3背后的想法orddict:append/3是您可以向同一个键添加更多值并保存所有值的列表。

链接地址: http://www.djcxy.com/p/38237.html

上一篇: Starting and Terminating child of simple

下一篇: Erlang spawn a supervisor with a parameter