扩展执行繁重计算的 node.js websocket 服务器

Posted

技术标签:

【中文标题】扩展执行繁重计算的 node.js websocket 服务器【英文标题】:Scaling a node.js websocket server that does heavy computations 【发布时间】:2020-08-15 07:32:36 【问题描述】:

我有一个 node.js 服务器,它有一个接收大量消息的 websocket 连接。该服务器还执行繁重的 cpu 工作。我看到 ws 连接不断丢弃/重新连接/丢弃/等。我的猜测是cpu工作阻塞了主线程这么多,同时ws收到这么多消息,ws连接就失败了?

我最初的解决方案是将所有 cpu 工作转移到一个节点 worker_thread,这有点帮助,但我仍然看到 ws 失去了很多连接。我的想法是,node 在网络 IO 上应该是超级高效的,所以如果我将所有 cpu 工作转移到另一个线程中,网络工作就不会被 cpu 工作阻塞。

服务器是有状态的,这个服务器只能有 1 个,所以我不能只是启动更多。

我不确定如何继续。一些想法是:

    将 cpu 工作移到另一个进程中,并通过某种进程间通信方法进行通信。但这比 worker_thread 好多少? 水平扩展 websockets,所以如果一个失败,其他人将弥补这一缺陷。以这种方式扩展 websocket 似乎相当复杂。

【问题讨论】:

"[...] 但我仍然看到 ws 经常失去连接。"这通常意味着您在主循环中仍有一些阻塞代码。出于好奇,你有多少并发连接,服务器每秒收到多少消息? 大约 30k 并发连接数,而且这个数字以后只会增加。至于多少 msg/sec,我不知道,但我真的应该知道。我正在使用 crossbar.io,所以它应该有一些用于统计的 API。每个连接每 5 分钟发送 1 条消息,每 10 分钟发送 1 条消息。 【参考方案1】:

第一名 -

//服务器是有状态的,这个服务器只能有1个,所以我 不能只是旋转更多。

你应该去掉这个瓶颈。只要你有这个,你将无处可去。扩展的想法是在应用程序的副本之间分配网络和 cpu 工作负载。

如果您的服务器是有状态的,请创建一个状态控制器服务器来处理所有状态信息。启动应用程序的副本并在副本和状态控制器服务器之间建立集群内通信。

完成此设置后,创建一个负载平衡器,它可以单独检查副本的就绪情况并将流量转发到可用的副本。不要忘记,在 Node JS 中,网络处理发生在内核级别。因此,该操作系统机制将在第一线处理负载并保持请求等待,直到工作负载准备好处理它们。此设置允许您控制阈值,例如副本数量和就绪超时 - 这可以为性能微调扫清道路。这些调整取决于您的请求数据、响应数据、处理时间等事实。

好消息是几乎所有的容器编排系统都提供了以上所有功能。大多数情况下,您必须自己处理处理状态的服务器。

https://kubernetes.io/docs/concepts/cluster-administration/networking/ https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

【讨论】:

嗯,你怎么知道我在 k8s 上?看到您的回答后,我才添加了 k8s 标签。无论如何,你的建议是我将有状态的 cpu 工作转移到一个单独的进程中,并横向扩展接受 ws 连接的应用程序? 是的。底线是,如果你需要更多的计算能力,只有新的 CPU 才能提供。如果您需要更多的网络吞吐量,则需要更多的网络接口和 agin, cpus 来处理它们。编排提供了这一点,您需要抓住它们。

以上是关于扩展执行繁重计算的 node.js websocket 服务器的主要内容,如果未能解决你的问题,请参考以下文章

在 react (Node.JS) 中使用繁重/耗时的函数

nodejs是单线程还是多线程

AVA实战总结:面向未来的Node.js测试框架

AWS:按需运行计算繁重的进程(Windows 可执行文件)

javascript 在执行异步操作时使用工作线程进行繁重计算的示例

如何将 QProcess 的执行与 QProgressBar 的推进联系起来以实现非常繁重的计算循环