使用ActionCable仅向房间中的一个Web套接字广播

问题描述 投票:0回答:2

我正在使用ActionCable来提供易于实现的浏览器通知。当用户在浏览器中打开多个选项卡并且我需要将数据仅发送到一个选项卡,即只发送到用户房间中的一个WebSocket时,问题就出现了。如何才能做到这一点?

ruby-on-rails websocket ruby-on-rails-5 actioncable
2个回答
0
投票

使用pub / sub方法无法直接隔离单个pub / sub客户端,因为整个想法是发布者不了解订阅者。

但是,有两种常见的方法可以解决这个问题:

  1. 每个连接使用不同的命名通道,将命名通道保存在数据库中,并将所有消息转发到该特定命名通道(即将通道user-ID-TIMESTAMP保存在数据库中并将其用作目标连接)。
  2. 另一种更可靠的方法(虽然更复杂)是将消息发送给所有客户端,但创建一个竞争条件,只允许单个客户端接收实际消息。这看起来像这样: 服务器向所有客户端发送“您有消息”。 客户端轮询来自服务器的“未传递”消息。 服务器锁定消息池或使用数据库事务以检索未传递的消息并将消息标记为已传递。服务器将未传递的消息发送到客户端(可选地设置ACK超时)。 单个客户端连接接收未传递的消息,其余的获得一个空的消息数组(因为它们都被传递到另一个客户端)或接收“已传递”标志,因此数据被更新但不会引发通知。 (可选)客户端发送和确认。 (可选)服务器将消息传递标记为已完成。如果在“超时”之前未收到ACK,则服务器取消标记传送并重新发送“您有消息”消息。

祝好运!


0
投票

每次建立新连接时,我们都会创建一个新房间。因此,例如当用户建立新连接时,我们可以将房间名称作为用户:user_id:some_unique_random_string,它可以等于用户:user_id:123j123b1h2b1j23bh12b3,当同一个用户通过打开另一个选项卡建立另一个连接时,我们也会执行同样创建一个单独的房间。现在,ActionCable提供的一件事是我们可以找到所有房间名称后跟任何前缀。

让用户已经建立了三个连接,他们的房间是用户:128:123n1jh123ko9876,用户:128:asdas23412cs1234,用户:128:asni9202h5i3jens然后我们也可以使用ActionCable获取这些房间名称。

user_id = 128
pubsub = ActionCable.server.pubsub
channel_with_prefix = pubsub.send(:channel_with_prefix, RoomChannel.channel_name)
channels = pubsub.send(:redis_connection).pubsub('channels', "#{channel_with_prefix}:users:#{user_id}:*")

现在,频道是一个由房间名称组成的数组。

所以puts channels

["chatapp_production:users:128:123n1jh123ko9876", "chatapp_production:users:128:asdas23412cs1234", "users:128:asni9202h5i3jens"]

这就是我们如何在不使用任何外部数据库和API调用的情况下找到与单个用户相关的所有房间的方法。

© www.soinside.com 2019 - 2024. All rights reserved.