如何在Phoenix中使用客户端订阅特定响应来构建Web套接字服务器?

时间:2017-12-04 21:35:01

标签: websocket elixir phoenix-framework

我正在开发一个Web套接字服务器,我需要使用Phoenix Framework向我的客户发送实时消息。

我的网络套接字服务器的基本思想是客户端可以订阅某种类型的信息并期望只接收它,其他客户端永远不会收到它,除非他们也订阅它,相同的信息被广播给每个人(且只有)客户实时订阅了它。

此外,这些信息按类别和子类别分开,最多可分为4个类别。

因此,举例来说,假设我有两种类别信息CatACatB,每个类别都可以包含子类别,因此CatA可以CatA.SubCatACatA.SubCatB子类别,每个子类别也可以有其他子类别,依此类推。

这些信息由服务生成,每个根类别一个(它们也处理子类别的所有信息),因此我们有CatAServiceCatBService。这些服务需要在服务器启动时运行,始终生成新信息并将其广播给订阅它的任何人。

现在,我的客户会尝试订阅这些信息,我现在的解决方案是为每种可用的信息类型设置一个频道,这样客户端就可以加入一个频道来接收频道类型的信息。

为此我在js代码中有类似的东西:

let channel = socket.channel("CatA:SubCatA:SubSubCatA", {})
channel.join()
channel.on("new_info", (payload) => { ... }

在这种情况下,我会有一个频道,所有感兴趣的SubSubCatA来自SubCatA CatA的客户都可以加入,而CatA的服务会生成和广播所有子类别的信息等等。

我不确定我是否能够准确地解释我想要的东西,但是如果有什么不清楚的地方,请告诉我什么,以便我能更好地解释它,同样,我把这个(非常糟糕)的图像作为一个例子所有沟通将如何发生https://ibb.co/fANKPb

另外,请注意我每个类别只能有一个频道,并为加入该类别频道的所有人广播所有子类别信息,但我非常关注性能和网络带宽,所以我的目标是只发送仅向请求它的客户提供信息。

在这里做一些测试,似乎如果客户端加入了如上面js代码中所示的通道,我可以这样做:

MyServerWeb.Endpoint.broadcast "CatA:SubCatA:SubSubCatA", "new_info", message

并且该客户端(以及所有其他客户端正在监听该频道,但只有这样)才会收到该消息。

所以,我的问题分为两部分,一部分是更通用的,是实现上述内容的正确方法。

第二个是如果我已经提出的解决方案是解决这个问题的好方法,因为我不确定字符串“CatA:SubCatA:SubSubCatA”的长度是否会在服务器解析它时产生开销或者是否存在开销是其他一些我不知道的限制。

谢谢!

1 个答案:

答案 0 :(得分:1)

您必须为每个类别的客户制作单独的频道,并且根据您获得的ID,您可以在检查加入频道的客户后广播消息

 def join("groups:" <> group_slug, _params, socket) do
%{team_id: team_id, current_user: user} = socket.assigns

case Repo.get_by(Group, slug: group_slug, team_id: team_id) do
  nil ->
    {:error, %{message: "group not found"}}
  group ->
    case GroupAuthorization.can_view?(group.id, user.id) do
      true ->
        messages = MessageQueries.group_latest_messages(group.id, user)
        json = MessageView.render("index.json", %{messages: messages})
        send self(), :after_join
        {:ok, %{messages: json}, assign(socket, :group, group)}
      false ->
        {:error, %{message: "unauthorized"}}
    end
end

这是仅向订阅并加入群组的群组中的用户发送消息的示例。希望这会有所帮助。