2015-10-18 45 views
11

我的問題是,一個可以從一個版本升級方案中修改一個已經運行的監督者的重啓強度閾值,分開,如果是的話,怎麼樣?二郎主管動態變化重啓強度

這是從來沒有上來過,但運行主管與最初沒有孩子,以便使其他進程由主管的方式開始兒童: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個孩子足夠的寬容,但說一萬個孩子,我想能夠增加它...並減少它作爲孩子的數量由於正常終止下降。

回答

9

有這樣做沒有API,所以我相信你堅持的升級方法,除非你想通過submitting a pull request提出爲此對OTP隊一個新的API提供的代碼修改,新的測試一個完整的補丁,文檔更改。

這樣做還有一個非常骯髒的黑客方式,涉及操縱內部監督者狀態,所以這絕對不是我推薦的生產系統,但我認爲它仍然很有趣。 A 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文檔介紹,這些功能僅適用於DEB ugging的目的,所以用它們在生產系統中這樣做絕對不是我推薦的。這裏的第二個參數replace_state表明,這種方法需要的supervisor內部狀態的記錄,這是我們通過rr shell命令得到這裏的細節知識,所以如果該記錄都沒有改變,這個代碼可能會停止工作。更脆弱將治療supervisor狀態記錄作爲一個元組並在intensity場計數是在一個特定的元組位置,這樣你就可以改變它的值。因此,如果您真的想要改變主管重啓強度的功能,您最好長期向OTP團隊建議添加它;如果你打算採取這樣的路線,我建議首先提出關於erlang-questions mailing list的想法來衡量興趣。

+1

太好了,謝謝,如果不是解決方案,這是一個答案,如果你打折這個你爲我們開採的相當有趣但很難看的寶石!我想我們都同意這是最好留在地上的寶石之一,或者安全地重新埋葬!我會考慮你的建議,發佈功能建議和拉動請求等。對我來說,這似乎是一個非常有效的功能,很明顯,如果假設變量均勻且死亡機會相等,則靜態重啓強度和間隔永遠不會最佳,其中總關鍵程度在整個運行集中共享。謝謝你的時間! – Michael

0

一個解決辦法是嵌套的監督員。但主要的問題是你想通過這種重啓強度達到什麼目的。當你想要殺死主管時,強度需要是一些非常錯誤的指示,例如一個需要的資源意外不可用。

+1

感謝您的回覆,但我認爲我不得不說,這應該是一個評論 - 這不是一個答案,而且一個動態的監督者樹會從FAR實現,從微不足道的 - :which_children/2將不再工作;人們必須編寫代碼來修改樹狀圖以找到所有的孩子,從樹中選擇一個監督員是一項工作,我不想考慮所有這些監督員的重新啓動規範。我認爲用這種方式編寫一個像鞋拔頭人那樣做一個想做的人的主管,會更容易。 – Michael

+1

主管人員處理同類過程的另一個問題是,例如,如果您有15個主管,並且其中10個主管有100個故障,這可能足以導致主管崩潰,也可能是頂層級別的主管會崩潰......但如果100次崩潰分散在15而不是10次,那麼最高級別可能會存活......整個事件的行爲將變得不一致。 – Michael

+0

@Michael,實際上我相信遍歷假設假設每個孩子崩潰時的頂級崩潰(和其他問題只用'gproc'或簡單的'ets table'解決我認爲),行爲將是一致的 – Lol4t0