Docker容器和Node.js集群

37

我有一个运行在Node.js上的API服务器,之前使用了其集群模块,并且测试看起来很好。现在我们的IT部门想要转向使用Docker容器,这让我很高兴,但除了玩一下之外,我实际上从未使用过它。但我有一个想法,Node.js应用程序在单个Docker进程中运行,因此集群模块并不是最好的选择,因为单个Docker进程可能是设置中的瓶颈点,直到请求通过集群模块在该进程内分割。

所以说,对于能够在飞行中启动和停止的Docker容器集群而言,比起使用Node.js的集群模块,显然更加重要,对吗?

如果我有一个容器群集,那么使用Node.js的集群模块会给我带来什么呢?API端点返回时间少于0.5秒(通常更少)。

我正在使用MySQL(目前应该只是单个服务器),因此不需要使用数据完整性解决方案。


1
我正在开始这条路,很好奇你的情况如何 - 我也想知道你是否像下面的评论者提到的那样使用pm2或只是forever。 - maehue
1
我正在使用AWS ElasticBeanstalk,因此如果节点命令失败并退出,则Docker容器将停止,然后由于我的扩展配置,EB会自动启动另一个。到目前为止,不使用集群模块非常好,我们的实例大约运行10%-15%的CPU利用率。 - Mitchell Simoens
3个回答

25
我所见过在使用 Docker 时最好的解决方案是尽可能减少每个容器中的进程数,因为容器很轻量级;你不希望进程尝试使用超过一个 CPU。因此,在容器中运行集群不会增加任何价值,反而可能会加剧延迟。
这里 https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef#.9x6j3b8vw Chad Robinson 以一般性的概念解释了这个想法。
Kubernetes、Rancher、Mesos 和其他容器管理层处理负载均衡。它们提供“调度”(将这些 Docker 容器切片移动到不同的 CPU 和机器上,以实现对集群的良好利用)和“网络”(将入站请求负载平衡到这些容器中)内部层。 更新 我认为值得添加链接 为什么建议在容器中仅运行一个进程?,人们可以分享他们的想法和经验,但主要来自 Jon的一些有趣观点:
只要将单个职责(单个进程、函数或关注点)赋予容器: Docker 将其命名为“关注点”是个好主意;)
  • 水平扩展容器更加容易。
  • 它可以在不同的项目中重复使用。
  • 与在整个应用程序环境中进行问题识别和故障排除相比,识别问题和故障排除会更加轻松。此外,日志记录和报告可以更准确和详细。
  • 升级/降级可以逐步和完全控制。
  • 安全性可以应用于特定资源和不同级别。

我不确定这种方法在与k8s结合时是否能够实现规模化。例如,我们有一个nodejs应用程序,需要18个进程来舒适地处理负载峰值。每个容器只有1个进程,那就是18个docker容器,每个都有自己的开销。如果1个进程达到100%的CPU使用率并且请求开始排队,容器将通过基本健康检查被检测为“停机”,而实际上它只是CPU受限。容器将被重新启动,这将导致更多问题。允许2或3个进程将使健康检查不太可能因为一个长时间运行的进程而失败。 - Aaron Butacov
5
我认为理想情况不是一个进程,而是一个关注点在nodejs网络应用程序中,因为多个子进程控制了你可以同时处理的请求数。混合两个不同的应用程序不是一个好的做法,但是多个子进程使你的应用程序更加稳定,并且允许一个进程失败并重新启动,而不需要整个容器需要被重新调度。 - Aaron Butacov
嘿@AaronHarun,那很有道理。我还没有去过k8s,只在AWS ECS和AWS Fargate上进行了测试。这里有另一个讨论,提到了相同的权衡。通常并不存在适用于所有问题的完美解决方案,取决于你的堆栈、团队和环境,你需要在可能的情况下进行测试后做出决定。;)你应该在这里添加另一个答案,陈述你的考虑。我会点赞的。 - tiomno

20

你需要进行测量以确保,但我的直觉是使用 node 的集群模块运行会很值得。它会在最少的额外开销下获得更多的 CPU 利用率。不需要管理额外的容器(启动、停止、监控)。而且集群工作进程具有高效的通信机制。在我看来,最合理的演变(不要跳过步骤)似乎是:

  1. 1 个容器,1 个 node 进程
  2. 1 个容器,多个集群化的 node 工作进程
  3. 多个容器,每个容器都有多个 node 工作进程

1
PM2非常受欢迎。它使用集群技术,已经有几个针对PM2的Docker镜像。 - tsturzl
那么,我说容器将可以访问CPU的多核心,这种说法是正确的吗? - Mitchell Simoens
如果Docker不支持多核,那将是一个巨大的缺陷。 - Peter Lyons
7
我想知道大家对以下文章的看法,文章称在 Docker 的背景下,“管理和协调自己资源的进程不再那么有价值。相反,像 Kubernetes、Mesos 和 Cattle 这样的管理堆栈已经普及了这种资源应该被整个基础设施管理的概念。”并且,“在这种环境中,试图使用过多 CPU 核心的进程可能会成为一个麻烦制造者。” 链接:https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef - Harindaka
4
我曾经完成了一个项目,移除了node.js集群模块,只在容器层面进行了扩展,结果还不错。我认为“尝试使用过多CPU核心”的概念可能会误导人。即使启用了集群模块,Node也会为每个CPU核心启动一个工作进程,但即使如此,内核仍会分配CPU负载。总的来说,我同意“docker中可能没有集群”,但凭借特定环境中的实际测量,集群化可能是有益的。 - Peter Lyons
显示剩余2条评论

0

我有一个拥有4个逻辑核心的系统,我在我的机器上以及安装在同一台机器上的docker上运行了以下命令。

const numCPUs = require('os').cpus().length;
console.log(numCPUs)

这行代码在我的机器上打印出4,在Docker容器内部打印出2。这意味着如果我们只在Docker容器中使用集群,那么只会运行2个实例。因此,Docker容器看到的核心数与实际机器不同。同时,在启用集群模式的情况下运行5个Docker容器将得到10个机器实例,最终由操作系统内核管理,其中包括4个逻辑核心。

因此,我认为最好的方法是在Swarm模式下使用多个Docker容器实例,并禁用Node.js集群。这应该可以获得最佳性能。


3
你确定不是因为你的开发电脑上有默认的docker设置吗?你可以手动管理docker资源(如CPU核心、内存等)。例如,在Windows上:https://docs.docker.com/docker-for-windows/ - LagSurfer
谢谢,@LagSurfer 这正是我的问题。 - intumwa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接