使用 node.js 应用程序和套接字 io 进行水平缩放

Horizontal scaling with a node.js app & socket io

我和我的团队正在开发数字标牌平台。

我们有 ~ 2000 Raspberry Pi 世界各地使用 Socket IO 连接到 Nodejs 服务器。 Raspberries 正在启动连接。

我们希望能够在多台服务器上水平扩展我们的应用程序,但我们遇到了一个无法解决的问题。

基本上,应用程序将连接的 Raspberry 的套接字存储在一个数组中。 我们有一个在服务器内调用 API 的外部程序,这是由服务器通过 API 调用搜索哪些套接字将 "impacted" 并向它们发送信息的结果。

经过大量搜索,我们假设我们必须将套接字(或它们的 ID)存储在其他地方(Redis?),以使应用程序无状态。然后,任何服务器都可以响应 API 调用并在中央位置查看套接字。

遗憾的是,我们找不到有关如何执行此操作的任何详细示例。

你能帮帮我们吗?

谢谢

(您不能将来自多个服务器实例的套接字存储在像 redis 这样的共享数据存储中:它们仅在启动它们的服务器的上下文中才有意义)。

您将需要 node.js 个服务器集群来处理此问题。有多种方法可以创建集群。它们都涉及将来自 RPis 的传入连接定向到 "generic" 主机名,例如 server.example.com。 server.example.com 主机名后面将是多个 node.js 服务器。

来自每个 RPi 的每个传入连接只连接到多个服务器中的一个。 (我相信你知道这一点。)这意味着你的集群中有一个 node.js 服务器 "owns" 每个单独的 RPi。

(告诉您如何组建 node.js 服务器集群超出了本答案的范围。提示:循环 DNS 或反向代理 nginx 前端。)

然后,您希望将来自每个 API 调用的传入数据路由到集群中的每个服务器,以便服务器可以将其路由到它拥有的 RP。

这是处理该问题的好方法:

  1. 设置redis 缓存或其他共享数据存储。它可以很小。
  2. 当每个 node.js 服务器启动时,将其注册为活动服务器。也就是说,让它将自己用于处理 API 调用的特定地址放入共享服务器。具体地址大概是12.34.56.78:3000的形式:即一个IP地址和端口。
  3. 让每台服务器每隔一段时间更新一次该地址,大约一分钟一次,以表明它仍然存在。
  4. 当 API 调用到达 server.example.com 时,它将到达或多或少随机选择的 node.js 服务器实例。
  5. 让那个服务器从redis缓存中读取服务器地址列表
  6. 让该服务器重复 API 对除自身以外的所有服务器的调用。将 repeated=yes 之类的参数添加到重复的 API 调用中。
  7. 然后,每个服务器查看其连接的套接字列表并执行您的应用程序所需的操作。
  8. 在服务器关闭时,让服务器自行取消注册——从 Redis 中删除它的地址——如果可能的话。

换句话说,构建一种将 API 调用分散到集群中所有活动 node.js 服务器的方法。

如果这必须扩展到非常大的数量(超过一百个左右)node.js 服务器,或者每分钟数百个 API 调用,您可能应该调查使用消息排队软件。

保护您的 REDIS 服务器免受互联网上随机 cybercreeps 的侵害。