Как лучше всего запустить gen_server на всех узлах в кластере Erlang?

Я создаю инструмент мониторинга на Erlang. При запуске в кластере он должен запускать набор функций сбора данных на всех узлах и записывать эти данные с помощью RRD на одном узле «записывающего устройства».

В текущей версии на главном узле (rolf_node_sup) работает супервизор, который пытается запустить второй супервизор на каждом узле кластера (rolf_service_sup). Затем каждый из супервизоров на узле должен запустить и контролировать группу процессов, которые отправляют сообщения обратно на gen_server на главном узле (rolf_recorder).

Это работает только локально. Ни на одном удаленном узле не запущен супервизор. Чтобы загрузить -узел-супервизор от узла регистратора:

rpc:call(Node, supervisor, start_child, [{global, rolf_node_sup}, [Services]])

Я нашел пару человек, предполагающих, что супервизоры на самом деле предназначены только для локальных процессов. Например.

Каков наиболее эффективный способ OTP для реализации моего требования иметь контролируемый код, работающий на всех узлах в кластере?

  • Распределенное приложение предлагается в качестве альтернативы распределенному дереву супервизора. Это не подходит для моего варианта использования. Они обеспечивают переключение между узлами, но поддерживают выполнение кода на наборе узлов.
  • Интересен модуль pool. Однако он обеспечивает выполнение задания на узле, который в настоящее время наименее загружен, а не на всех узлах.
  • В качестве альтернативы я мог бы создать набор контролируемых «прокси-процессов» (по одному на узел) на главном сервере, которые используют proc_lib:spawn_link для запуска супервизора на каждом узле. Если что-то пойдет не так на узле, прокси-процесс должен умереть, а затем быть перезапущен его супервизором, который, в свою очередь, должен перезапустить удаленные процессы. Здесь может быть очень полезен модуль подчиненный.
  • Или, может быть, я слишком усложняю. Непосредственное наблюдение за узлами - плохая идея, вместо этого, возможно, мне следует спроектировать приложение для сбора данных более слабосвязанным способом. Создайте кластер, запустив приложение на нескольких узлах, скажите одному, чтобы он стал мастером, и оставьте все как есть!

Некоторые требования:

  • Архитектура должна быть способна справляться с присоединением узлов к пулу и выходом из него без ручного вмешательства.
  • Я хотел бы построить решение с одним мастером, по крайней мере на начальном этапе, для простоты.
  • Я бы предпочел использовать существующие возможности OTP вместо ручного кода в моей реализации.

person afternoon    schedule 03.04.2011    source источник


Ответы (2)


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

Насколько я понимаю вашу программу, вы хотите иметь один главный узел, на котором вы запускаете свое приложение. Это запустит виртуальную машину Erlang на узлах кластера. Модуль pool использует для этого модуль slave, который требует связи ssh на основе ключей в обоих направлениях. Это также требует, чтобы у вас был правильно работающий DNS.

Недостатком slave является то, что если ведущее устройство умирает, то умирают и ведомые устройства. Это сделано намеренно, поскольку оно, вероятно, идеально подходит для исходного варианта использования, однако в вашем случае это может быть глупо (вы можете по-прежнему собирать данные, даже если мастер не работает, например)

Что касается приложений OTP, каждый узел может запускать одно и то же приложение. В вашем коде вы можете определить роль узлов в кластере, используя конфигурацию или обнаружение.

Я бы посоветовал запустить виртуальную машину Erlang с помощью некоторого средства ОС, daemontools или чего-то подобного. Каждая виртуальная машина будет запускать одно и то же приложение, причем одно будет запущено как ведущее, а остальные как ведомые. У этого есть недостаток, заключающийся в том, что ему труднее «автоматически» запускать программное обеспечение на машинах, входящих в кластер, как вы могли бы сделать с slave, однако он также намного надежнее.

В каждом приложении у вас может быть подходящее дерево надзора в зависимости от роли узла. Удаление межузлового контроля и порождения значительно упрощает систему.

Я также предлагаю передать все узлы мастеру. Таким образом, ведущему устройству не нужно беспокоиться о том, что происходит на ведомом устройстве, он может даже игнорировать тот факт, что узел не работает. Это также позволяет добавлять новые узлы без каких-либо изменений в мастере. Файл cookie может использоваться для аутентификации. Несколько мастеров или записывающих устройств также было бы относительно легко.

Однако «подчиненные» узлы должны будут следить за тем, чтобы мастер спускался и поднимался, и предпринимать соответствующие действия, такие как сохранение данных мониторинга, чтобы он мог отправить их позже, когда мастер будет резервным.

person knutin    schedule 03.04.2011
comment
Читая источник Риака, я склоняюсь к этому. - person afternoon; 04.04.2011
comment
Выбирая способ делать это, как Риак, или полагаясь на способ делать это так, как я предлагал? Кроме того, хотя Riak Core очень интересен, я не понимаю, как он будет полезен в вашем случае, поскольку Riak Core в основном помогает вам направлять запросы на нужный сервер и перемещать вещи при необходимости. - person knutin; 04.04.2011
comment
Наклоняясь к тому пути, который вы предлагаете. В riak_core есть несколько хороших принципов, которые я хотел бы позаимствовать, но я согласен с тем, что полное хешированное кольцо не является правильным решением для этого приложения. - person afternoon; 05.04.2011

Я бы посмотрел на riak_core. Он обеспечивает уровень инфраструктуры для управления распределенными приложениями поверх необработанных возможностей erlang и самого otp. В riak_core ни один узел не должен быть назначен главным. Ни один узел не является центральным в смысле ОТП, и любой узел может взять на себя другие отказавшие узлы. В этом суть отказоустойчивости. Более того, riak_core обеспечивает элегантную обработку узлов, присоединяющихся к кластеру и покидающих его, без необходимости прибегать к политике главный / подчиненный.

Хотя такая «топологическая» децентрализация удобна, распределенные приложения обычно нуждаются в логически особых узлах. По этой причине узлы riak_core могут объявлять, что они предоставляют определенные услуги кластера, например, как воплощено в вашем варианте использования, узел сборщика результатов.

Другой интересной особенностью / архитектурным следствием является то, что riak_core предоставляет механизм для поддержания глобального состояния, видимого для членов кластера через протокол «сплетен».

По сути, riak_core включает в себя набор полезного кода для разработки высокопроизводительных, надежных и гибких распределенных систем. Ваше приложение кажется достаточно сложным, поэтому наличие прочной основы принесет дивиденды раньше, чем позже.

otoh, документации пока почти нет. :(

Вот парень, который рассказывает о внутреннем приложении AOL, которое он написал с помощью riak_core:

http://www.progski.net/blog/2011/aol_meet_riak.html

Вот примечание о шаблоне арматурного стержня:

http://lists.basho.com/pipermail/riak-users_lists.basho.com/2011-March/003632.html

... и вот сообщение о разветвлении этого шаблона арматурного стержня:

https://github.com/rzezeski/try-try-try/blob/7980784b2864df9208e7cd0cd30a8b7c0349f977/2011/riak-core-first-multinode/README.md

... поговорим на riak_core:

http://www.infoq.com/presentations/Riak-Core

... объявление riak_core:

http://blog.basho.com/2010/07/30/introduction-riak-core/

person mwt    schedule 03.04.2011
comment
Спасибо, что расширили свой ответ. Я знал о riak_core, но не был уверен, подходит ли он. Рекламные услуги на специальных узлах очень интересны. Я думаю, что это приложение все еще немного выходит за рамки целевой области проблем riak_core. Я пока буду использовать простой OTP. По мере того, как riak_core будет лучше документироваться, и если приложение окажется полезным, я могу переключиться на него. - person afternoon; 05.04.2011