Phoenix 的实时接口建立在两个默认的公共抽象之上,一个套接字接口,客户端通过它连接 - 这通常是一个 websocket(尽管它可以回退到长轮询或使用其他传输),这是“线" 在客户端和您的服务器之间创建。通常,您通过令牌调解此连接,以决定客户端是否能够打开该套接字连接。它在user_socket.ex 中指定。
然后你就有了通道接口,它是一个带有特定句柄 (api) 的 gen_server,用于通过“电线”接收传入的消息。您还可以拥有允许订阅频道(“加入”)的授权逻辑,并且它可能因频道(甚至主题)而异。
每个客户端可以连接到 1 个套接字和 0 到 N 个通道。在下面,连接到通道的客户端只是(简化)将给定的套接字注册到发布者订阅者接口(Phoenix 的 PubSub),并为订阅该特定组合的每个套接字拥有一个处理这些“通道:房间”的过程。
如果您从iex shell 启动:observer.start,然后转到Processes 选项卡,然后从两个不同的客户端加入完全相同的“频道:主题”,您将看到两个渠道进程,不是一个。如果您从 Elixir.YourWeb.PubSub.Local0 看到应用程序树,您还会看到 2 个进程“连接”到/从它。
这意味着当您从前端发出channel.leave() 时,您的服务器会从您刚刚“离开”的“频道”中取消订阅该客户端,并且正在处理它的进程将被关闭。通道离开是从特定的channel:topic 组合中取消订阅特定的套接字(客户端)。这不会干扰连接到同一主题的其他客户端。在这种情况下,插座(“电线”)仍处于连接状态。您可以重新加入频道,或加入其他频道,而无需“请求”(协商)再次连接到套接字。
另一方面,如果您发出socket.disconnect(),您将“拔掉电线”,因此从之前订阅的所有频道中取消订阅该特定套接字(客户端)。这使得与给定套接字相关的所有进程都关闭,但也不会干扰其他客户端的套接字/连接/订阅。
如果所有客户端都离开给定通道(通过“离开”或“断开”它们的套接字),您将看到该给定通道不会有任何进程在运行。一旦另一个客户加入该频道,就会为该特定客户和频道创建一个流程:主题。
tldr;回答你的问题:
但是,如果您有长时间运行的进程,这些进程是从频道本身产生的,那么当没有客户端连接到该特定频道:主题时,应该关闭该进程,那么您当然需要确保清理它们。除了 Erlang 的常规监控功能外,Phoenix 还有一个 Presence 界面,让您也可以对其进行跟踪。