Запуск из супервизора нескольких воркеров на основе одного и того же gen_server.

254 views
Skip to first unread message

Роман А.

unread,
Aug 27, 2012, 9:27:24 AM8/27/12
to erlang-...@googlegroups.com
Здравствуйте, знатоки Erlang/OTP!

Подскажите, пожалуйста, новичку, как правильно сделать такую штуку: супервизор, следящий за несколькими воркерами, созданными на основе одного и того же модуля с поведением gen_server - просто он вызывается с разными параметрами.

Делаю вот так, но почему-то срабатывает только Test_process1.

%% код супервизора:
-module(testapp01_sup).
-behaviour(supervisor).
-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    io:format('***  SUPERVISOR:INIT() is called *** ~n', []),
    Test_process1 = {test1, {test_srv, start_link, [[test1, 12, 34]]}, permanent, brutal_kill, worker, [test_srv]},
    Test_process2 = {test2, {test_srv, start_link, [[test2, 56, 78]]}, permanent, brutal_kill, worker, [test_srv]},
    {ok, { {one_for_one, 5, 10}, [Test_process1, Test_process2]}}.


%% а этот код в сервере, ничего необычного:
-module(test_srv).
-behaviour(gen_server).
-export([init/1]).
-record(state, {}).

start_link(Params) ->
    gen_server:start_link({local, ?SERVER}, ?SERVER, [Params], []).

init(Params) ->
    io:format('test_srv:init() has been called. Params: ~p ~n', [Params]),
    {ok, #state{}}.


Заранее спасибо!

Artem Artemev

unread,
Aug 27, 2012, 9:38:29 AM8/27/12
to erlang-...@googlegroups.com
ты регистрируешь их под одинаковыми именами:
      gen_server:start_link({local, ?SERVER}, ?SERVER, [Params], []).

Best Regards,
Artem Artemev



27 августа 2012 г., 17:27 пользователь Роман А. <romkasi...@gmail.com> написал:

--
--
Страница рассылки: http://groups.google.com/group/erlang-russian
Новости: http://erlanger.ru
Чат: xmpp://erl...@conference.jabber.ru
Чат для оффтопа: xmpp://erlang...@conference.jabber.ru
 
Написать письмо: erlang-...@googlegroups.com
Отписаться: erlang-russia...@googlegroups.com
 
 

Un Lexx

unread,
Aug 27, 2012, 9:41:16 AM8/27/12
to erlang-...@googlegroups.com
-  gen_server:start_link({local, ?SERVER}, ?SERVER, [Params], []).
+  gen_server:start_link(?SERVER, [Params], []).

и обращатся к этим воркерам можно либо через gproc либо pg2 если не важно какой из воркеров

27 августа 2012 г., 19:38 пользователь Artem Artemev <art....@gmail.com> написал:

Роман А.

unread,
Aug 27, 2012, 9:53:44 AM8/27/12
to erlang-...@googlegroups.com
Спасибо! Видимо дело было в кривых руках и недостатке практики.

Вдогонку вопрос: стоит ли навешивать воркеры на глобальный супервизор от Application или лучше сделать "дочерний" и уже такие вот воркеры навешивать на него?

Paul Peregud

unread,
Aug 27, 2012, 10:08:34 AM8/27/12
to erlang-...@googlegroups.com
Лучше на дочерний. Простой повод - легче изолировать причины вылетания
программы.

2012/8/27 Роман А. <romkasi...@gmail.com>:

Volodymyr Stolyarchuk

unread,
Oct 21, 2012, 10:32:33 AM10/21/12
to erlang-...@googlegroups.com
У меня похожий вопрос, так что не хочеть создавать новую тему

Есть конревой супервизор, у которого есть ребенок simple_one_for_one супервизор, который и порождает однотипных воркеров

Так вот вопрос в том где их правильно порождать? Так как мне надо прочитать даные из чего-то там и потом создать несколько таких воркеров. Я пробую их порождать сразу после создания корневого супервизора вот так:
    demo_sup:start_link(),
    demo_sup:start_worker(1),
    demo_sup:start_worker(2).

Они создаються, все хорошо. Но когда я убиваю последнего созданого воркера, он умират и все приложение падает

=SUPERVISOR REPORT==== 21-Oct-2012::17:21:50 ===
     Supervisor: {local,demo_workers_sup}
     Context:    child_terminated
     Reason:     killed
     Offender:   [{pid,<0.47.0>},
                  {name,undefined},
                  {mfargs,{demo_worker,start_link,undefined}},
                  {restart_type,temporary},
                  {shutdown,2000},
                  {child_type,worker}]


=CRASH REPORT==== 21-Oct-2012::17:21:50 ===
  crasher:
    initial call: application_master:init/4
    pid: <0.42.0>
    registered_name: []
    exception exit: killed
      in function  application_master:terminate/2 (application_master.erl, line 229)
    ancestors: [<0.41.0>]
    messages: []
    links: [<0.6.0>]
    dictionary: []
    trap_exit: true
    status: running
    heap_size: 610
    stack_size: 24
    reductions: 3025
  neighbours:

=INFO REPORT==== 21-Oct-2012::17:21:50 ===
    application: demo
    exited: killed
    type: temporary

Если я убиваю первого воркера, он умирает и приложение продолжает работать.

Когда я создаю воркера из консоли он создаеть и умирает без любых последствий для всего приложения, потому я чувствую что не надо создавать дочирные процессы из метода start/2 приложения. Хотелось бы понять причину такого поведения

Сам пример приложение разместил на github

Спасибо)

Volodymyr Stolyarchuk

unread,
Oct 21, 2012, 10:41:21 AM10/21/12
to erlang-...@googlegroups.com
Вот как выглядит приложение в appmon
Screenshot from 2012-10-21 17:38:48.png

Sergey Prochorov

unread,
Oct 21, 2012, 7:44:46 PM10/21/12
to erlang-...@googlegroups.com
Если у тебя прям так и написано

start(_, _) ->
    demo_sup:start_link(),
    demo_sup:start_worker(1),
    demo_sup:start_worker(2).

То ничего удивительного, т.к. start/2 должна вернуть Pid корневого супервизора, а у тебя возвращает Pid 2-го воркера.
Сделай так:

start(_, _) ->
    Supervisor = demo_sup:start_link(),
    demo_sup:start_worker(1),
    demo_sup:start_worker(2),
    Supervisor.


Но, возможно, кто-то лучше подскажет где этих воркеров нужно стартовать - мне тоже интересно. может лучше внутри demo_sup:start_link/0 ?

воскресенье, 21 октября 2012 г., 18:41:21 UTC+4 пользователь Volodymyr Stolyarchuk написал:

Andy

unread,
Oct 22, 2012, 4:49:59 AM10/22/12
to

Если я правильно понял вопрос, то порождать воркеров надо за пределами your_sup:init, то есть послать сообщение (например init2) себе. Я наступал на эти грабли. Ну и у воркеров лучше иметь двухступенчатую инициализацию, иначе при проблемах в worker:init процесс тихо умирает по (якобы) непонятной причине. Или я так и не научился читать между строк логов :)

On Sunday, October 21, 2012 5:32:34 PM UTC+3, Volodymyr Stolyarchuk wrote:
У меня похожий вопрос, так что не хочеть создавать новую тему

Есть конревой супервизор, у которого есть ребенок simple_one_for_one супервизор, который и порождает однотипных воркеров

Так вот вопрос в том где их правильно порождать? Так как мне надо прочитать даные из чего-то там и потом создать несколько таких воркеров. Я пробую их порождать сразу после создания корневого супервизора вот так:
    demo_sup:start_link(),
    demo_sup:start_worker(1),
    demo_sup:start_worker(2).

Они создаються, все хорошо. Но когда я убиваю последнего созданого воркера, он умират и все приложение падает


Volodymyr Stolyarchuk

unread,
Oct 22, 2012, 5:00:51 AM10/22/12
to erlang-...@googlegroups.com
Да, спасибо, проблема именно в этом

start(_, _) ->
    Supervisor = demo_sup:start_link(),
    demo_sup:start_worker(1),
    demo_sup:start_worker(2),
    Supervisor.

работает так как мне надо

даже если запускать внутри demo_sup:start_link/0, надо тоже делать что-то такое

    Sup = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
    demo_sup:start_worker(1),
    demo_sup:start_worker(2),
    Sup.
Reply all
Reply to author
Forward
0 new messages