websocket - Phoenix websocket socket.disconnect() vs. channel.leave()
问题描述
I'm reading through the phoenix docs on ways to disconnect from a socket or leave a channel.
My naive understanding is that channel#leave
Unsubscribes from server events, and instructs the channel to terminate on server
and socket#disconnect
maintains the channel server-side, allowing for reconnection.
So, my question is when to use one vs. the other.
It sounds like there are 2 cases to consider:
- There are other clients subscribed to the same channel, so
#leave
would cut-off their connection, favoring a#disconnect
. - But if there is user/account attrition, NEVER calling
leave
maintains "dead" channels on the server and for long-running processes this could be an issue?
Am I thinking about this correctly? Should we implement periodic cleanup tasks to kill long-running, "dead" channels if we choose to roll with #disconnect
-only?
Thanks!
解决方案
Phoenix 的实时接口建立在两个默认的公共抽象之上,一个 socket 接口,客户端通过它连接 - 这通常是一个 websocket(尽管它可以回退到 longpolling 或使用其他传输),这是“电线”,即在客户端和您的服务器之间创建。通常,您通过令牌调解此连接,以决定客户端是否能够打开该套接字连接。它在user_socket.ex
.
然后你有通道接口,它是一个带有特定句柄 (api) 的 gen_server,用于通过“电线”接收传入的消息。您还可以拥有授权逻辑以允许订阅频道(“加入”),并且它可能因频道(甚至主题)而异。
每个客户端可以连接到 1 个套接字和 0 到 N 个通道。在下面,连接到通道的客户端只是(简化)将给定套接字注册到发布者订阅者接口(Phoenix 的 PubSub),并为订阅该特定组合的每个套接字的那些“通道:房间”处理。
如果您:observer.start
从iex
shell 启动,然后转到Processes
选项卡,然后从两个不同的客户端加入相同的“通道:主题”,您将看到将有两个通道进程,而不是一个。如果您从 Elixir.YourWeb.PubSub.Local0 看到应用程序树,您还将看到 2 个进程“连接”到/从它。
这意味着当您channel.leave()
从前端发出 a 时,您的服务器会从您刚刚“离开”的“通道”中取消订阅该客户端,并且处理它的进程将被关闭。channel:topic
通道离开是从该特定组合取消订阅特定套接字(客户端) 。这不会干扰连接到同一主题的其他客户端。在这种情况下,插座(“电线”)仍处于连接状态。您可以重新加入频道,或加入其他频道,而无需“请求”(协商)再次连接到套接字。
另一方面,如果您发出socket.disconnect()
“拔掉电线”,并因此从之前订阅的所有频道中取消订阅该特定套接字(客户端)。这使得与给定套接字相关的所有进程都关闭,但也不会干扰其他客户端的套接字/连接/订阅。
如果所有客户端都离开给定通道(通过“离开”或“断开”它们的套接字),您将看到该给定通道不会有任何进程运行。一旦另一个客户加入该频道,就会为该特定客户和频道创建一个流程:主题。
tldr; 回答你的问题:
1) 没有
2) 没有
但是,如果您有从通道本身内部产生的长时间运行的进程,那么当没有客户端连接到该特定通道:主题时应该关闭该进程,那么您当然需要确保清理它们。除了 Erlang 的常规监控功能外,Phoenix 还有一个 Presence 界面,它也允许您跟踪它。
推荐阅读
- webpack - Webpack 无法解析“babel-loader”
- javascript - 构建 API 时,解析服务器上的业务逻辑在哪里?
- bash - 在 zsh 脚本中传播第 n 个参数之后的所有参数
- angular - Angular + Electron - 构建和分发 URL
- java - 如何使用 Spring5 WebClient 进行异步调用
- python-3.x - 将 Cassandra 与 Python 连接的有效方法(抑制警告)
- javascript - 使用 Flask 应用程序热重载 VanilaJS 或在每次 src 更改时创建 bundle.js
- c# - 以编程方式设置 httpErrors existingResponse "PassThrough" ASP.NET MVC
- google-cloud-platform - 我正在尝试将 Project Creator 角色授予 GCP 中 IAM 的服务帐户
- javascript - 无法将数组作为数组操作