2015-10-18 14 views
11

Câu hỏi của tôi là, có thể sửa đổi ngưỡng cường độ khởi động lại của người giám sát đang chạy, ngoài kịch bản nâng cấp phát hành, và nếu có, làm thế nào?Erlang giám sát thay đổi năng động để khởi động lại cường độ

Nó không bao giờ đưa ra trước đó, nhưng chạy một người giám sát với ban đầu không có con, do đó quá trình khác bắt đầu trẻ em bằng cách giám sát: start_child/2, do sup init của tôi/1 là như thế này:

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

Vào thời điểm người giám sát bắt đầu, số lượng trẻ em có thể chưa biết; chắc chắn nó có thể thay đổi đáng kể từ 10, đến 10.000, hoặc nhiều hơn.

Cường độ khởi động lại nói 20 là đủ rộng cho 10 trẻ em, nhưng nói 10.000 trẻ em tôi muốn có thể tăng ... và giảm số lượng trẻ em giảm do chấm dứt bình thường.

Trả lời

9

Không có API để thực hiện việc này, vì vậy tôi tin rằng bạn bị kẹt với phương pháp nâng cấp trừ khi bạn muốn đề xuất API mới cho nhóm OTP bằng cách submitting a pull request cung cấp bản vá hoàn chỉnh với các thay đổi mã, kiểm tra mới và thay đổi tài liệu.

Có một cách hack thực sự bẩn thỉu để thực hiện điều này liên quan đến việc thao túng trạng thái giám sát nội bộ, và vì vậy nó hoàn toàn không phải là điều tôi muốn giới thiệu cho hệ thống sản xuất. A supervisor lưu trữ cường độ khởi động lại trong trạng thái vòng lặp bên trong của nó. Bạn có thể xem trạng thái này bằng cách gọi số sys:get_state/1,2 về quy trình giám sát. Ví dụ, đây là tình trạng của một người giám sát trong 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 = []} 

Các rr lệnh ban đầu lấy các định nghĩa kỷ lục từ supervisor vì vậy chúng tôi có thể nhìn thấy tên trường khi chúng tôi nhận nhà nước từ yaws_sup, nếu không chúng tôi sẽ chỉ nhận được một bộ đầy đủ các giá trị ẩn danh.

Nhà nước lấy ra cho thấy cường độ trong trường hợp này là 0. Chúng ta có thể thay đổi nó bằng cách sử 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 = []} 

số thứ hai của chúng tôi để sys:replace_state/2 mất một kỷ lục quốc gia như một đối số và thay đổi lĩnh vực intensity của nó đến 2 Các hàm sys:replace_state/2,3 trả lại trạng thái mới và như bạn có thể thấy gần cuối kết quả ở đây, intensity giờ là 2 thay vì 0.

Vì tài liệu sys:replace_state/2,3 giải thích, các chức năng này chỉ dành cho deb mục đích ugging, do đó, sử dụng chúng để làm điều này trong một hệ thống sản xuất chắc chắn không phải là một cái gì đó tôi khuyên bạn nên. Đối số thứ hai cho replace_state ở đây cho thấy rằng phương pháp này đòi hỏi kiến ​​thức về các chi tiết của hồ sơ trạng thái nội bộ của supervisor, mà chúng tôi thu được ở đây thông qua lệnh shell rr, vì vậy nếu bản ghi đó thay đổi, mã này có thể ngừng hoạt động. Thậm chí mong manh hơn sẽ xử lý hồ sơ nhà nước supervisor như một tuple và đếm trên lĩnh vực intensity để ở một vị trí tuple cụ thể để bạn có thể thay đổi giá trị của nó.Do đó, nếu bạn thực sự muốn chức năng này thay đổi cường độ khởi động lại của người giám sát, thì tốt nhất là bạn nên sử dụng nhóm OTP trong thời gian dài để bổ sung; nếu bạn định đi theo lộ trình đó, tôi khuyên bạn nên đề xuất ý tưởng trên erlang-questions mailing list để đánh giá sự quan tâm.

+1

Thật tuyệt vời, cảm ơn, đó là một câu trả lời, nếu không phải là một giải pháp, nếu bạn giảm giá đá quý khá thú vị nhưng xấu xí này bạn đã khai thác cho chúng tôi!Tôi nghĩ tất cả chúng ta đều đồng ý rằng đây là một trong những viên đá quý tốt nhất còn lại trong lòng đất, hoặc có thể được trả lại một cách an toàn! Tôi sẽ xem xét đề xuất của bạn về việc đăng đề xuất tính năng và yêu cầu kéo, v.v. Có vẻ như một tính năng hoàn toàn hợp lệ đối với tôi thực sự, rõ ràng không có cường độ khởi động lại tĩnh và khoảng thời gian có thể tối ưu nếu bạn giả định biến đồng nhất với cơ hội tử vong bằng nhau , trong đó tổng mức độ phê phán được chia sẻ trên tập hợp đang chạy. Cảm ơn vì đã dành thời gian cho tôi! – Michael

0

Một giải pháp là tổ chức giám sát của bạn. Nhưng câu hỏi chính là bạn muốn đạt được những gì bằng cường độ khởi động lại này. Cường độ khi bạn muốn giết người giám sát cần phải là dấu hiệu cho một điều gì đó rất sai, ví dụ: một tài nguyên cần thiết bất ngờ không có sẵn.

+1

Cảm ơn bạn đã trả lời, nhưng tôi nghĩ rằng tôi phải nói rằng, đây không phải là câu trả lời và một cây giám sát năng động sẽ là FAR từ tầm thường để thực hiện tốt - những thứ như người giám sát : which_children/2 sẽ không hoạt động nữa; người ta sẽ phải viết mã để recurse lên cây sup để tìm tất cả các trẻ em, chọn một giám sát trong cây để đẻ trứng từ là một công việc, và tôi thậm chí không muốn suy nghĩ về các thông số kỹ thuật khởi động lại của tất cả các giám sát viên. Tôi nghĩ rằng IMO sẽ dễ dàng hơn để viết một giám sát viên đã làm những gì người ta muốn hơn là người giám sát còi giày theo cách này. – Michael

+1

Một vấn đề khác với cây giám sát để xử lý một quy trình đồng nhất, ví dụ nếu bạn có 15 người giám sát, và có 100 vụ tai nạn trên 10 người, điều đó có thể đủ để người giám sát sụp đổ và có thể là hàng đầu người giám sát cấp sẽ sụp đổ ... nhưng nếu 100 vụ đụng độ trên 15 thay vì 10, cấp cao nhất có thể tồn tại ... Hành vi của toàn bộ sự việc sẽ trở nên không nhất quán. – Michael

+0

@Michael, thực sự tôi tin rằng giả thuyết Ergodic giả định rằng hành vi sẽ nhất quán nếu tai nạn cấp cao nhất trên mọi vụ tai nạn trẻ em (và các vấn đề khác được giải quyết chỉ với 'gproc' hoặc' bảng đơn giản' tôi nghĩ) – Lol4t0

Các vấn đề liên quan