Erlang管理员动态更改重启强度

我的问题是,除了发布升级方案之外,是否可以修改已运行的主管的重新启动强度阈值,如果是这样,如何呢?

这是从来没有出现过,但运行一个监督最初没有孩子,所以另一个进程启动孩子通过主管的方式: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到10000甚至更多。

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


这样做没有API,所以我相信你一直坚持升级方法,除非你想通过提交一个pull请求来提供一个新的API给OTP团队,提供一个包含代码更改,新测试和文档的完整补丁变化。

这也涉及到操纵内部监督者状态的一种非常肮脏的黑客方式,所以这绝对不是我为生产系统推荐的东西,但我认为它仍然很有趣。 supervisor在其内部循环状态supervisor存储重启强度。 您可以通过在管理程序进程中调用sys:get_state/1,2来查看此状态。 例如,以下是Yaws Web服务器中的主管的状态:

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第二个参数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问题邮件列表中提出这个想法来衡量兴趣。


一种解决方案是嵌套你的主管。 但主要的问题是你想通过这种重启强度达到什么目的。 当你想要杀死主管时,强度需要作为一个非常错误的指示,例如一个需要的资源意外地不可用。

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

上一篇: Erlang supervisor dynamic change to restart intensity

下一篇: server exception exit: noproc