Erlang internal pubsub server

338 views
Skip to first unread message

Denis F.

unread,
Jan 14, 2013, 7:32:24 AM1/14/13
to erlang-...@googlegroups.com
Всем привет.

Я сейчас пытаюсь написать эффективную реализацию механизма pubsub для эрланговых процессов. Если вдруг окажется, что существует такая вещь (а я искал - не нашел) - подскажите и не читайте дальше :)

Первая проблема - эффективная рассылка сообщений. Самый простой вариант - отправка сообщения прямо из handle_* функции, пробежавшись по списку пидов-получателей из стейта процесса (наколеночный получасовой код лежит тут: http://github.com/shizzard/ebus). Второй вариант, который сразу приходит на ум - отправка сообщений из короткоживущего процесса, который спаунится специально для рассылки одного сообщения и сразу умирает после выполнения этой задачи. Собственно, вопрос: какой вариант правильнее? Может, существует еще один способ такой рассылки, который будет быстрее.

Вторая проблема - хранение списка получателей (процессов, подписанных на канал). Самый простой способ, опять же - хранить их в стейте процесса канала, как это и реализовано в ebus. Проблема в том, что если процесс канала упадет, канал потеряет пиды всех получателей, что недопустимо. Можно хранить список в ETS, но мне такая реализация не кажется эффективной (дергаенье ETS на каждом паблише в канал и создание по одной табличке на канал). Можно получить "гибридный" вариант - все изменения списка получателей кладутся в ETS, но рассылка производится по списку, "закешированному" в стейте процесса. Является ли этот вариант оптимальным?

Третья проблема - что делать, если процесс канала таки упал. Нужно каким-либо образом уведомить клиентов канала (а это не только слушатели, но и паблишеры) о том, что процесс помер. Если со слушателями здесь проще - слушателю, в принципе, пофигу от какого pid ему сообщение из канала приедет - то с паблишерами сложнее. Можно использовать gproc, но тогда каждый паблиш будет лезть в gproc, что, как я понял из изучения исходников, приводит к чтению данных из ETS. Есть ли какое-нибудь эффективное решение подобной проблемы?

Maxim Sokhatsky

unread,
Jan 14, 2013, 7:37:01 AM1/14/13
to erlang-...@googlegroups.com
PubSub механизм есть очень эффективный и элегантный в gproc.
Например что бы создать чат из процессов учасников чата вы делаете:
gproc:reg({p,l, main_room})
И рассылаете все данные с помощью:

gproc:send({p,l,main_room},Data)

Прежде чем писать свое, вниметельно посмотрите, такие вещей море,
с масштабом от двух строчек заканчивая RabbitMQ. 



Date: Mon, 14 Jan 2013 04:32:24 -0800
From: m...@shizz.ru
To: erlang-...@googlegroups.com
Subject: Erlang internal pubsub server
--
--
Страница рассылки: http://groups.google.com/group/erlang-russian
Новости: http://erlanger.ru
Чат: xmpp://erl...@conference.jabber.ru
Чат для оффтопа: xmpp://erlang...@conference.jabber.ru
Правила, действующие в чате и рассылке: http://erlanger.ru/ru/erlang-at-conference-jabber-ru
 
Написать письмо: erlang-...@googlegroups.com
Отписаться: erlang-russia...@googlegroups.com
 
 

Dreyk G

unread,
Jan 14, 2013, 7:35:42 AM1/14/13
to erlang-...@googlegroups.com
А чем pg или pg2  Не нравится?
--

Defnull

unread,
Jan 14, 2013, 8:41:41 AM1/14/13
to erlang-...@googlegroups.com
Лично мне в gproc_ps не нравится следующий момент: если, например, все подписчики у меня благополучно завершились, то я не узнаю об этом в процессе которые делает всем publish. А если он получает довольно большой объём сообщений, то было бы не плохо его вырубать на время когда подписчиков нету. Можно конечно вручную проверять перед отправкой или по таймеру или вешать свои мониторы на подписчиков, но это всё как-то не тру.

понедельник, 14 января 2013 г., 16:37:01 UTC+4 пользователь Maxim Sokhatsky написал:

Andy

unread,
Jan 16, 2013, 6:52:14 AM1/16/13
to erlang-...@googlegroups.com
gen_event не подойдет?

Max Lapshin

unread,
Jan 16, 2013, 7:32:55 AM1/16/13
to erlang-...@googlegroups.com
Этот тред хорошая иллюстрация к тому тезису, что комет-серверы людям нужны разные.

Для задач нужен кролик с транзакционной очередью, для веб-комета tinymq или наш dps. Для внутриэрланга gen_event самое то
--

Денис Фахртдинов

unread,
Jan 16, 2013, 8:04:27 AM1/16/13
to erlang-...@googlegroups.com
И правда, что-то я о gen_event совсем забыл.
По поводу gproc: я посмотрел реализацию механизма, о котором говорил Максим. Думается мне, что этот механизм не будет работать оптимальным образом в приложении, где пабсаб является чуть ли не ядром (я изначально говорил о высокоэффективной реализации пабсаба): все пиды получателей лежат в одной табличке, для выборки используется match и т.п. Но в любом случае спасибо, я примерно понял в какую сторону смотреть.

16 января 2013 г., 16:32 пользователь Max Lapshin <max.l...@gmail.com> написал:

Max Lapshin

unread,
Jan 16, 2013, 10:12:52 AM1/16/13
to erlang-...@googlegroups.com
«Думается», «кажется», «высокоэффективная реализация».

Эти вещи лучше вместе не держать. Если нужно быстро, надо знать насколько быстро.

Когда мы с Димой Демещуком готовился к банальному докладу, мы проверяли на нескольких разных профилях нагрузки.
Так что сначала надо распланировать нагрузку: один канал, много подписчиков или много канало и малоподписчкиков на каждом.
Есть ли слоны и т.п.


2013/1/16 Денис Фахртдинов <m...@shizz.ru>

Денис Фахртдинов

unread,
Jan 16, 2013, 10:29:24 AM1/16/13
to erlang-...@googlegroups.com
Я могу сказать абсолютно точно, что в моем приложении будет очень много каналов (сотни и тысячи), большая часть которых будет содержать небольшое количество клиентов (5-10, не больше). Меньшая часть каналов будет обслуживать довольно большое количество клиентов (сотни). Так как каналов много, получателей в десятки раз больше - выборка match'ем и одной паблик таблички явно не кажется оптимальным решением, независимо от количества пересылаемых сообщений.

16 января 2013 г., 19:12 пользователь Max Lapshin <max.l...@gmail.com> написал:

Max Lapshin

unread,
Jan 16, 2013, 10:48:30 AM1/16/13
to erlang-...@googlegroups.com
опять «кажется».

Собирай стенд да проверяй. Возможно match и не лучший вариант (можно bag) взять, но не исключено, что это будет мелочью.





2013/1/16 Денис Фахртдинов <m...@shizz.ru>

Денис Фахртдинов

unread,
Jan 16, 2013, 1:04:48 PM1/16/13
to erlang-...@googlegroups.com
Да, Макс, я понял твою мысль, спасибо. Уже решил, что первую версию (прототип) нужно писать на gproc, а потом уже решать вопросы производительности.

16 января 2013 г., 19:48 пользователь Max Lapshin <max.l...@gmail.com> написал:

Valery Meleshkin

unread,
Jan 17, 2013, 4:34:42 AM1/17/13
to erlang-...@googlegroups.com
В ETS ты совершенно зря сомневаешься :) Особенно если вместо match по ordset пользовать lookup по bag. Можно делать процесс обслуживающий канал (подписки, слеженение за смертью подписчиков, это решило бы и описанную Defnull проблему), который владеет protected ETS'кой, чтобы ETS не дох вместе с процессом можно пользовать heir. Ещё, в случае рассылки на основе ETS, неплохо бы делать backpressure на основе длины очереди сообщений процесса получателя.

среда, 16 января 2013 г., 19:29:24 UTC+4 пользователь Denis F. написал:


2013/1/16 Денис Фахртдинов <m...@shizz.ru>
Чат: xmpp://erlang@conference.jabber.ru
Чат для оффтопа: xmpp://erlang-talks@conference.jabber.ru

Правила, действующие в чате и рассылке: http://erlanger.ru/ru/erlang-at-conference-jabber-ru
 
Написать письмо: erlang-russian@googlegroups.com
Отписаться: erlang-russian+unsubscribe@googlegroups.com
 
 

Defnull

unread,
Jan 17, 2013, 5:52:55 AM1/17/13
to erlang-...@googlegroups.com
Ну то есть в итоге подписчика будет мониторить и gproc и процесс о котором ты говоришь. Тогда уж проще вообще выкинуть gproc и писать самому. =)

Max Lapshin

unread,
Jan 17, 2013, 6:05:03 AM1/17/13
to erlang-...@googlegroups.com
А никто не говорит, что gproc обязательно эталонный вариант =)

Есть большая разница между тысячами каналов по 20 пользователей и 20 каналами на тысячи подписчиков.


2013/1/17 Defnull <defin...@gmail.com>
Ну то есть в итоге подписчика будет мониторить и gproc и процесс о котором ты говоришь. Тогда уж проще вообще выкинуть gproc и писать самому. =)

--

Денис Фахртдинов

unread,
Jan 17, 2013, 6:27:47 AM1/17/13
to erlang-...@googlegroups.com
Макс, вот об этом я и говорил :) Просто реализация, которую я увидел в gproc, _очевидно_ неоптимальна.

17 января 2013 г., 15:05 пользователь Max Lapshin <max.l...@gmail.com> написал:

Valery Meleshkin

unread,
Jan 18, 2013, 2:47:12 AM1/18/13
to erlang-...@googlegroups.com
Непотимальна _для чего_? ИМХО gproc очень оптимален с точки зрения получения работающего софта завтра к утру ;)
Потом берёшь basho_bench + fprof/eprof и смотришь можно ли быстрее и надо ли.

четверг, 17 января 2013 г., 15:27:47 UTC+4 пользователь Denis F. написал:

Max Lapshin

unread,
Jan 18, 2013, 4:27:12 AM1/18/13
to erlang-...@googlegroups.com
Опять по кругу ходим.  «очевидно неоптимальна», «высокие нагрузки», «кажется» и ни единой цифирки замеров.
Ну померяй уже хоть что-нибудь.


2013/1/18 Valery Meleshkin <nekro...@gmail.com>

Станислав Мирошник

unread,
Oct 6, 2014, 8:04:25 AM10/6/14
to erlang-...@googlegroups.com
Всем привет, ребят тоже начал пользоваться gproc, для web своего проекта возникла необходимость получения не всех зарегистрированных процессов, а только определенного типа, ну к примеру регистрирую я их 

gproc:reg({n, l, {self(), WebPage, EventType}})

WebPage - ключ определенной страницы
EventType - ключик, чтобы на вебе по нему маршрутизировать в  необходимую вью для отображения

и вот нужно мне отослать сообщения всем кто находиться на рутовой  странице (WebPage в этом случае имеет значение -  root) и тут все ступор)))

Как выбрать именно этих клиентов и отправить сообщение всем кто на этой странице? 

Aleksey Kluchnikov

unread,
Oct 7, 2014, 12:09:30 AM10/7/14
to erlang-russian
Смотрите gproc:select, gproc:pid_looku.

Мне субъективно кажется что это не совсем использование gproc по назначению.

Кто нибудь мерял его быстродействие, сколько операций в секунду он
дает. Можно ли его делать как центральный реестр для всего и вся?

Для вашего случая может лучше хранить массив pidов на страничке, со
всеми сокетами юзеров которые на ней находятся?

6 октября 2014 г., 16:04 пользователь Станислав Мирошник
<dp070...@gmail.com> написал:
> --
> Вы получили это сообщение, поскольку подписаны на группу "Erlang по-русски".
> Чтобы отменить подписку на эту группу и больше не получать от нее сообщения,
> отправьте письмо на электронный адрес
> erlang-russia...@googlegroups.com.
> Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный
> адрес erlang-...@googlegroups.com.
> Чтобы настроить другие параметры, перейдите по ссылке
> https://groups.google.com/d/optout.

Max Lapshin

unread,
Oct 7, 2014, 2:17:42 AM10/7/14
to erlang-...@googlegroups.com
Я вам могу сразу сказать: если gproc:select делает именно ets:select, то этим нельзя пользоваться для выборки данных в основном режиме работы.

Для подписки процесса на канал есть ets bag и в нём надо делать ets:lookup.  ets:select работает чрезвычайно медленно

Andrew Gopienko

unread,
Oct 7, 2014, 5:05:40 AM10/7/14
to erlang-...@googlegroups.com
Если вы не упираетесь в производительность ets:select, то можно вот так:

3> gproc:add_local_property({root,evt1},1).
true
4> gproc:add_local_property({root,evt2},2).
true
5>
5> gproc:lookup_local_properties({root,'_'}).
[{<0.1508.0>,1},{<0.1508.0>,2}]


7 октября 2014 г., 13:17 пользователь Max Lapshin <max.l...@gmail.com> написал:
Я вам могу сразу сказать: если gproc:select делает именно ets:select, то этим нельзя пользоваться для выборки данных в основном режиме работы.

Для подписки процесса на канал есть ets bag и в нём надо делать ets:lookup.  ets:select работает чрезвычайно медленно

--

Станислав Мирошник

unread,
Oct 8, 2014, 3:41:51 AM10/8/14
to erlang-...@googlegroups.com
Спасибо за то что отозвались)
Reply all
Reply to author
Forward
0 new messages