免责声明:我对Erlang和OTP很新。
我想在Erlang / OTP中使用一个简单的pubsub,其中进程可以在某个“集线器”订阅并接收发送到该集线器的消息副本。
我知道gen_event
,但它在一个事件管理器进程中处理事件,而我希望每个订阅者都是一个独立的自治进程。而且,我无法理解gen_event
的处理程序监督。不幸的是,谷歌的结果充满了XMPP(Ejabberd)和RabbitMQ链接,所以我找不到任何与我的想法相关的内容。
我的想法是这样的pubsub模型无缝映射到监督树。所以我想扩展主管(引擎盖下的gen_server
)以便能够向其所有孩子发送一条演员信息。
我在快速而肮脏的自定义“调度程序”行为中攻击了这个:
-module(dispatcher).
-extends(supervisor).
-export([notify/2, start_link/2, start_link/3, handle_cast/2]).
start_link(Mod, Args) ->
gen_server:start_link(dispatcher, {self, Mod, Args}, []).
start_link(SupName, Mod, Args) ->
gen_server:start_link(SupName, dispatcher, {SupName, Mod, Args}, []).
notify(Dispatcher, Message) ->
gen_server:cast(Dispatcher, {message, Message}).
handle_cast({message, Message}, State) ->
{reply, Children, State} = supervisor:handle_call(which_children, dummy, State),
Pids = lists:filter(fun(Pid) -> is_pid(Pid) end,
lists:map(fun({_Id, Child, _Type, _Modules}) -> Child end,
Children)),
[gen_server:cast(Pid, Message) || Pid <- Pids],
{noreply, State}.
然而,虽然一切看起来一切正常(孩子们收到消息并在失败时无缝重启),但我想知道这是个好主意。
请某人,批评(或批准)我的方法,和/或推荐一些替代方案吗?
答案 0 :(得分:11)
我最近使用gproc来实现pubsub。自述文件的例子可以解决问题。
subscribe(EventType) ->
%% Gproc notation: {p, l, Name} means {(p)roperty, (l)ocal, Name}
gproc:reg({p, l, {?MODULE, EventType}}).
notify(EventType, Msg) ->
Key = {?MODULE, EventType},
gproc:send({p, l, Key}, {self(), Key, Msg}).
答案 1 :(得分:10)
从你的代码中我看起来gen_event处理程序是一个完美的匹配。
处理程序回调是从一个调度消息的中央进程调用的,但这些回调不应该做太多工作。
因此,如果您需要为订阅者提供自己的状态的自治进程,只需在事件回调中发送消息。
通常这些自治进程是gen_servers,你只需要从你的事件回调中调用gen_server:cast。
监督是一个单独的问题,可以通过OTP附带的常规监督基础设施来处理。您希望如何进行监督取决于订户进程的语义。如果它们都是相同的服务器,则可以使用simple_one_for_one
作为示例。
在订阅者流程的init
回调中,您可以将gen_event:add_handler
次调用添加到事件管理器中。
如果你使用gen_event:add_sup_handler
函数来添加你的进程,如果你的语义适合你,你甚至可以使用事件管理器作为主管。
更好地了解gen_event的在线资源:Learn you some Erlang chapter
否则Erlang书籍都有一些gen_event介绍。可能是Erlang and OTP in Action
中最彻底的一个哦,顺便说一句:我不会因为这个原因而攻击你自己的主管。
答案 2 :(得分:1)
一个非常简单的示例,您自己完成所有操作都在我的基本chat_demo中,这是一个简单的基于Web的聊天服务器。查看chat_backend.erl
(或chat_backend.lfe
,如果您喜欢括号),允许用户订阅,然后他们将收到所有到达后端的邮件。虽然修改很简单,但它不适合监督树(虽然它确实使用proc_lib
来获得更好的错误消息)。
答案 3 :(得分:-2)
有时候,我读到了øMQ(ZeroMQ),它对不同的编程语言有很多绑定。
http://www.zeromq.org/bindings:erlang
如果它不是纯粹的erlang解决方案,那么这可能是一种选择。