Rails ApplicationCable 和 Channels 最佳实践?

Rails ApplicationCable and Channels best practice?

我目前正在使用 Rails 准备支持反应和反应本机应用程序。令牌用于身份验证。

我的应用程序中有两个功能需要 WebSockets:

我看到了两种实现 WebSockets 的方法:

两个独立的频道

第一个频道:NotificationChannel 我在客户打开应用程序时订阅,然后如果需要我广播某事

第二个频道:ChatChannel 我在打开聊天时订阅的频道,代码如下所示:

class ChatChannel < ApplicationCable::Channel
  def subscribed
    authorize_chat_room_id(params[:chat_room_id]) #
    stream_from "chat_channel_#{params[:chat_room_id]}"
  end

  # here methods for receiving data from client
  # maybe some other methods for tracking if sb is typing and so on
  # private authorize_chat_room_id method
end

在这种情况下,用户最多订阅 2 个频道,订阅聊天时只执行一次授权。

在这种方法中,当用户订阅频道时,我只授权一次,但是,我不知道打开 2 个频道而不是 1 个频道会如何影响服务器的性能。

一个通道

单通道将被称为:PersonalChannel,并负责所有信息流,代码看起来像这样:

  def subscribed
    stream_from "personal_channel_#{current_user.id}"
  end

  def send_message(data)
    if authorize_chat_room_id(data['chat_room_id'])
      #create message
    end
  end

  def start_typing(data)
    if authorize_chat_room_id(data['chat_room_id'])
      # some broadcast
    end
  end

当我广播时,我会发送有效载荷,例如类型(例如 'MESSAGE_SEND'),并基于此,如果聊天打开,React 客户端将打印消息。

这种方法的优点是在发送消息时我只能广播给一个用户并且我不会从频道收到消息。但是在这种情况下,我必须在每次执行操作时进行授权。

我的问题是哪种解决方案在性能方面会更好,什么是普遍接受的方法(使通道非常通用或让每个通道处理单个任务)?

在这个问题上,我建议您考虑将代码维护问题放在性能之上。

channels 的概念允许我们将发布者与消费者分离。这简化了大量代码并有助于分离关注点。

例如,在聊天室发帖的用户不需要知道(也不需要管理)有多少人订阅了该聊天室,也不需要知道他们可能是谁。这些问题现在由 pub/sub 系统而非用户处理。

这种关注点分离使得添加或删除聊天成员变得更加容易(您不需要更新每个用户,您只需要更新 pub/sub 系统)。

这种分离还可以防止存储数据的多个副本(pub/sub 系统保存唯一有效的副本)。

在漫长的 运行 中,通过将所有数据整合到一个 PersonalChannel,您将重新引入发布者和消费者之间的耦合 - 这将增加复杂性并使维护模式变得困难时间.

在聊天室示例中,每个用户都需要获取所有房间成员的副本并将每条消息发送给所有用户。这增加了(成员列表的)副本数量并引入了同步问题。

The advantage of this approach is that when sending the message I can broadcast only to one user and I won't get back message from the channel. But in this case, I have to authorize each time performed an action.

实际上,您可以使用第一种方法轻松实现这一优势,方法是为每个用户订阅一个个人频道以及其他频道,订阅三个频道而不是两个。