4

我正在尝试使用 ERlang、Cowboy、Websocket 和 gen_bunny 集成 websocket 聊天。

我能够让他们独立工作。

浏览器 -> Cowboy websocket chat (Works) Erlang and RabbitMQ AMQP (Works)

将它们集成在一起时,我能够从浏览器获取消息到 Cowboy 并将其传递给 RabbitMQ 并再次从 RabbitMQ 取回。

我什至可以将消息回复给发送消息的用户。但是,我想将消息广播给所有连接的用户。

据我了解,Erlang 将为每个用户创建一个单独的进程。那么,在我从 RabbitMQ 得到响应后,如何将它广播给所有连接的用户?

4

3 回答 3

2

正确——Cowboy 创建了一个运行 WebSocket 处理程序代码的每个连接进程。一种方法是让处理程序的websocket_init/3函数向“广播”进程注册自身(并在 中注销websocket_terminate/3)。从 RabbitMQ 接收到消息后,广播进程将消息重复到所有已注册的 WebSocket 连接,这些连接可以使用websocket_info/3处理程序回调接收它。

广播进程可以使用监视器来发现 WebSocket 处理程序何时死亡,并自动将其从注册列表中删除。

那么,处理程序的生命可能看起来像这样:

  1. websocket_init/3init/3在 Cowboy 执行(到 WebSocket)中请求的协议升级后调用。从这里,客户端处理程序broadcast向消息广播进程注册自己。
  2. 只要连接保持打开状态,处理程序就会接收到它的消息广播websocket_info/3,并通过返回将消息传递给客户端{reply, {text, Message}, State}
  3. 终止时,处理程序使用 注销自己broadcast。如果由于某种原因这不能按预期工作,broadcast请监控所有订阅者,以便收到他们死亡的通知。
于 2013-05-01T13:37:38.227 回答
1

看看 gproc 项目:https ://github.com/uwiger/gproc

它有一个 Pub/Sub 模式,您可以使用它来构建您提到的聊天。

来自 gproc 的 wiki:

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}). 
于 2013-05-01T20:05:21.863 回答
0

每个牛仔进程都有自己的 Rabbit 队列。广播将与通配符绑定一起使用。不涉及显式循环。您可以通过不进行相应绑定来使订阅成为可选。请参阅:如何设置队列以使所有订阅者都获取消息 - Rabbit MQ

于 2013-05-23T17:07:31.540 回答