Erlang主管动态改变重启强度

时间:2015-10-18 22:57:44

标签: erlang otp supervisor

我的问题是,除了在发布升级方案中,是否可以修改已经运行的主管的重启强度阈值,如果是,如何修改?

以前从来没有出现过,但是最初没有孩子的主管运行,所以另一个进程通过主管启动子进程:start_child / 2,所以我的sup init / 1是这样的:

init([]) ->
    RestartSt = {simple_one_for_one, 10, 10},
    ChSpec = [foo, {foo,start_link,[]}, transient, 1000, worker, [foo]}],
    {ok, {RestartSt, ChSpec}}.

在主管开始时,可​​能的儿童人数不详;当然它可以从10到10,000或更多变化很大。

对于10个孩子来说,20岁的重启强度足够慷慨,但对于说10,000个孩子,我希望能够增加它...并且随着孩子数量因正常终止而下降而减少。

2 个答案:

答案 0 :(得分:8)

没有这样做的API,所以我相信您仍然坚持使用升级方法,除非您想通过submitting a pull request向OTP小组提出新的API,提供完整的代码更改,新测试和文档更改的补丁。

这也是一种非常肮脏的黑客攻击方式,涉及操纵内部主管状态,所以它绝对不是我建议的生产系统,但我认为它仍然是有趣的是看。 supervisor存储内部循环状态的重启强度。您可以通过在主管进程上调用sys:get_state/1,2来查看此状态。例如,这里是Yaws web server中主管的状态:

1> rr(supervisor).
[child,state]
2> sys:get_state(yaws_sup).
#state{name = {local,yaws_sup},
       strategy = one_for_all,
       children = [#child{pid = <0.67.0>,name = yaws_sup_restarts,
                          mfargs = {yaws_sup_restarts,start_link,[]},
                          restart_type = transient,shutdown = infinity,
                          child_type = supervisor,
                          modules = [yaws_sup_restarts]},
                   #child{pid = <0.42.0>,name = yaws_server,
                          mfargs = {yaws_server,start_link,
                                                [{env,true,false,false,false,false,false,"default"}]},
                          restart_type = permanent,shutdown = 120000,
                          child_type = worker,
                          modules = [yaws_server]},
                   #child{pid = <0.39.0>,name = yaws_trace,
                          mfargs = {yaws_trace,start_link,[]},
                          restart_type = permanent,shutdown = 5000,
                          child_type = worker,
                          modules = [yaws_trace]},
                   #child{pid = <0.36.0>,name = yaws_log,
                          mfargs = {yaws_log,start_link,[]},
                          restart_type = permanent,shutdown = 5000,
                          child_type = worker,
                          modules = [yaws_log]}],
       dynamics = undefined,intensity = 0,period = 1,restarts = [],
       module = yaws_sup,args = []}

初始rr命令从supervisor检索记录定义,因此当我们从yaws_sup获取状态时,我们可以看到字段名称,否则我们只会得到一个充满匿名的元组值。

检索到的状态显示此情况下的强度为0.我们可以使用sys:replace_state/2,3更改它:

3> sys:replace_state(yaws_sup, fun(S) -> S#state{intensity=2} end).
#state{name = {local,yaws_sup},
       strategy = one_for_all,
       children = [#child{pid = <0.67.0>,name = yaws_sup_restarts,
                          mfargs = {yaws_sup_restarts,start_link,[]},
                          restart_type = transient,shutdown = infinity,
                          child_type = supervisor,
                          modules = [yaws_sup_restarts]},
                   #child{pid = <0.42.0>,name = yaws_server,
                          mfargs = {yaws_server,start_link,
                                                [{env,true,false,false,false,false,false,"default"}]},
                          restart_type = permanent,shutdown = 120000,
                          child_type = worker,
                          modules = [yaws_server]},
                   #child{pid = <0.39.0>,name = yaws_trace,
                          mfargs = {yaws_trace,start_link,[]},
                          restart_type = permanent,shutdown = 5000,
                          child_type = worker,
                          modules = [yaws_trace]},
                   #child{pid = <0.36.0>,name = yaws_log,
                          mfargs = {yaws_log,start_link,[]},
                          restart_type = permanent,shutdown = 5000,
                          child_type = worker,
                          modules = [yaws_log]}],
       dynamics = undefined,intensity = 2,period = 1,restarts = [],
       module = yaws_sup,args = []}

我们对sys:replace_state/2的第二个参数将状态记录作为参数,并将其intensity字段更改为2. sys:replace_state/2,3函数返回新状态,正如您在附近看到的那样在此结果的末尾,intensity现在是2而不是0。

正如sys:replace_state/2,3文档所解释的那样,这些函数仅用于调试目的,因此在生产系统中使用它们绝对不是我推荐的。这里replace_state的第二个参数表明这种方法需要了解supervisor的内部状态记录的详细信息,我们通过rr shell命令获取了这些记录,所以如果该记录曾经更改,此代码可能会停止工作。更脆弱的是将supervisor状态记录视为元组,并指望intensity字段处于特定的元组位置,以便您可以更改其值。因此,如果您真的想要更改主管重启强度的这一功能,那么从长远来看,您最好向OTP团队提出要添加的内容;如果您要采取这种方式,我建议您首先在erlang-questions mailing list上提出想法来衡量兴趣。

答案 1 :(得分:0)

一种解决方案是嵌套你的主管。但主要的问题是你希望通过这种重启强度实现什么目标。你想要杀死主管的强度需要表明一些非常错误的事情,例如:意外地无法获得所需的资源。

相关问题