Как gen_server Erlang start_link gen_server на другом узле?

У меня есть приложение Erlang, которое становится слишком ресурсоемким, чтобы оставаться на одном узле. Я нахожусь в процессе перемещения gen_servers из одного процесса в другой, что оказывается относительно простым. Я на последнем препятствии: заставить фабричный процесс, который создает эти gen_servers, создавать их на удаленном узле, а не на локальном. По умолчанию start_link явно запускается только локально, но я не вижу возможности изменить это.

Казалось бы, мне придется быть изобретательным с решением, и я хотел посмотреть, реализовал ли кто-нибудь что-то подобное с каким-либо успехом. IOW, какое рекомендуемое решение?

ИЗМЕНИТЬ

Я смотрю на цепочку вызовов, которые запускаются вызовом:

gen_server:start_link(?Module, Args, [])

gen_server:start_link/3:

start_link(Mod, Args, Options) ->
    gen:start(?MODULE, link, Mod, Args, Options).

род:старт/5:

start(GenMod, LinkP, Mod, Args, Options) ->
    do_spawn(GenMod, LinkP, Mod, Args, Options).

род: do_spawn/5:

do_spawn(GenMod, link, Mod, Args, Options) ->
    Time = timeout(Options),
    proc_lib:start_link(?MODULE, init_it,
                        [GenMod, self(), self(), Mod, Args, Options], 
                        Time,
                        spawn_opts(Options));

proc_lib:start_link/5:

start_link(M,F,A,Timeout,SpawnOpts) when is_atom(M), is_atom(F), is_list(A) ->
    Pid = ?MODULE:spawn_opt(M, F, A, ensure_link(SpawnOpts)),
    sync_wait(Pid, Timeout).

Что, наконец, подводит нас к самому интересному. Существует spawn_opt/4, который соответствует:

spawn_opt(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) ->
    ...
    ...

НО, есть один, который действительно был бы мне полезен:

spawn_opt(Node, M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) ->
    ...
    ...

Меня смущает, что это не раскрывается. Я понимаю, что существует риск того, что небрежный программист может попытаться сгенерировать gen_server:start_link процесс на узле erlang, который работает на Марсе, заблокировав вызов на полчаса, но, конечно же, это забота программистов. Я действительно застрял с изменением OTP или написанием какого-то специального решения?


person Sniggerfardimungus    schedule 12.09.2012    source источник


Ответы (2)


Мы не start_link сервер на удаленном узле напрямую. Для хорошей структуры программы и простоты мы запускаем отдельное приложение на удаленном узле, а создание удаленных процессов делегируем определенному процессу, работающему в удаленном приложении.

Поскольку связывание с процессом в основном предназначено для контроля или мониторинга, мы предпочитаем связывание с локальными супервизорами, а не с удаленными процессами. Если вам нужен статус активности любого удаленного процесса, я рекомендую erlang:monitor и erlang:demonitor.

Типичная распределенная установка:

Node1
+---------------+                          Node2
| App1          |                          +---------------+
|   Supervisor1 |  Proc Creation Request   | App2          |
|     Processes | -----------------------> |   Supervisor2 |
|     ......    |                          |      |
|     ......    |                          |      | Create Children
|     ......    |       Monitor            |      V
|     ......    | -----------------------> |     Processes |
+---------------+                          |     ......    |
                                           +---------------+
person l04m33    schedule 13.09.2012

Возможно, вам поможет модуль rpc. Особенно функция async_call.

person stemm    schedule 13.09.2012