9

免責事項: 私は Erlang と OTP にかなり慣れていません。

Erlang/OTP で単純な pubsub が必要です。プロセスは「ハブ」でサブスクライブし、そのハブに送信されたメッセージのコピーを受信できます。

については知ってgen_eventいますが、イベントを 1 つのイベント マネージャー プロセスで処理する一方で、すべてのサブスクライバーを個別の自律的なプロセスにしたいと考えています。また、私はgen_eventのハンドラーの監督を理解することができませんでした。残念ながら、Google の結果は 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}.

ただし、一見するとすべてがうまく機能しているように見えますが (子供はメッセージを受信し、失敗するとシームレスに再起動されます)、これが良いアイデアだったのはいつなのだろうかと思います。

誰かが私のアプローチを批判 (または承認) してくれませんか?

4

4 に答える 4

11

最近、gprocを使用してpubsubを実装しました。readmeの例でうまくいきます。

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}).
于 2011-09-10T18:38:00.723 に答える
10

あなたのコードから、gen_eventハンドラーは完全に一致しているように見えます。

ハンドラーのコールバックは、メッセージをディスパッチする1つの中央プロセスから呼び出されますが、これらのコールバックはあまり機能しないはずです。

したがって、サブスクライバーに対して独自の状態を持つ自律プロセスが必要な場合は、イベントコールバックでメッセージを送信するだけです。

通常、これらの自律型プロセスはgen_serversであり、イベントコールバックからgen_server:castを呼び出すだけです。

監視は別の問題であり、OTPに付属する通常の監視インフラストラクチャで処理できます。監視をどのように行うかは、サブスクライバープロセスのセマンティクスによって異なります。それらがすべて同一のサーバーである場合、simple_one_for_oneたとえばを使用できます。

initサブスクライバープロセスのコールバックではgen_event:add_handler、イベントマネージャーにそれらを追加する呼び出しを行うことができます。

gen_event:add_sup_handler関数を使用してプロセスを追加する場合は、このセマンティクスが適切であれば、イベントマネージャーをスーパーバイザーとして使用することもできます。

gen_eventをよりよく理解するためのオンラインリソース:Erlangの章を学ぶ

それ以外の場合、Erlangの本にはすべてgen_eventの紹介があります。おそらくErlangとOTPinActionで見つけることができる最も徹底的なものです

ああ、ところで:私はこれのためにあなた自身の監督者をハックするつもりはありません。

于 2011-08-30T17:20:22.657 に答える
1

すべてを自分で行う非常に単純な例は、単純な Web ベースのチャット サーバーである私の非常に基本的なchat_demoにあります。ユーザーがサブスクライブできるようにする(chat_backend.erlまたは括弧が好きな場合) を確認すると、バックエンドに到着するすべてのメッセージが送信されます。変更は簡単ですが、監視ツリーには適合しません (ただし、より良いエラー メッセージを取得するために使用されます)。chat_backend.lfeproc_lib

于 2011-08-31T13:49:34.197 に答える
-2

以前、さまざまなプログラミング言語へのバインディングが多数ある øMQ (ZeroMQ) について読んだことがあります。

http://www.zeromq.org/

http://www.zeromq.org/bindings:erlang

純粋な erlang ソリューションでない場合は、これを選択できます。

于 2011-08-31T06:41:34.570 に答える