Могу ли я вызвать функции клиента GenServer с удаленного узла?
У меня есть GenServer на удаленном узле с функциями реализации и клиента в модуле. Могу ли я использовать функции клиента GenServer удаленно?
С помощью GenServer.call({RemoteProcessName, :"app@remoteNode"}, :get)
работает, я ожидаю, но это громоздко.
Если я хочу очистить это, я прав, думая, что я должен был бы написать функции клиента на вызывающем (клиентском) узле?
3 ответа
Вы можете использовать :rpc.call/{4,5}
функции.
:rpc.call(:"app@remoteNode", MyModule, :some_func, [arg1, arg2])
Для большого количества звонков, лучше для пользователя gen_server:call/2-3
,
Если вы хотите использовать rpc:call/4-5
, вы должны знать, что это всего лишь один процесс с именем rex
на каждом узле для обработки всех запросов. Так что, если он работает один Mod:Func(Arg1, Arg2, Argn)
, Он не может ответить на другой запрос в это время!
TL;DR
да
обсуждение
Есть PID, сообщения, мониторы и ссылки. Ни больше ни меньше. Это твоя вселенная. (Если только вы не попадаете в некоторые довольно эзотерические аспекты реализации времени выполнения - но на уровне абстракции, представленном языками EVM, ранее заявленные элементы (должны) составляют вашу вселенную.)
В среде Erlang (локальной или распределенной в сетке) любой PID может отправлять сообщение, адресованное любому другому PID (посредник не требуется), а также устанавливать мониторы и так далее.
gen_server:cast
отправляет упакованное сообщение gen_server (таким образом, оно придет в виде handle_cast/2
будет вызвано). gen_server:call/2
устанавливает монитор и тайм-аут для получения помеченного ответа. Просто делаю PID ! SomeMessage
делает по существу то же самое, что и gen_server:cast
(отправляет сообщение) без какого-либо механизма gen_server, стоящего за ним (сложнее абстрагировать как интерфейс).
Это все, что нужно сделать.
Имея это в виду, конечно, вы можете использовать gen_server:call/2
через узлы, если они соединены в кластер / сетку через disterl. Два отключенных узла должны были бы взаимодействовать по-разному (сетевые сокеты) и не знали бы о внутреннем сопоставлении PID друг друга, но пока используется disterl, все они довольно легко переводят PID между собой. Именованные процессы - то, где вещи становятся немного хитрыми, но это является целью global
модуль и утилиты, такие как gproc
(хотя зависимость от таких объектов за определенной точкой обычно является признаком архитектурной проблемы).
Конечно, то, что PID любого узла может связываться с PID другого узла, не всегда означает, что они должны это делать. Физическая топология сети (пропускная способность, задержка, дрожание) вступает в игру, когда вы начинаете отправлять высокочастотные или большие сообщения (много gen_server:call
s), и вы всегда должны думать о допустимости разбиения - но для разгрузки тяжелых видов работ (редко) или физического разделения подсистем в очень большой системе (более часто) прямая отправка сообщений - очень простой способ взять программу, закодированную для одного узла, и распределить ее по кластеру.
(Учитывая все это, довольно редко можно увидеть используемый модуль rpc.)