Docker 容器和 Node.js 集群
Posted
技术标签:
【中文标题】Docker 容器和 Node.js 集群【英文标题】:Docker containers and Node.js clusters 【发布时间】:2015-04-17 08:26:12 【问题描述】:我有一个运行 Node.js 的 api 服务器,它正在使用它的集群模块,并且测试看起来相当不错。现在,我们的 IT 部门想转而使用 Docker 容器,我对此很满意,但除了玩玩之外,我从未真正使用过它。但我有一个想法,Node.js 应用程序在单个 Docker 进程中运行,因此集群模块并不是最好的,因为单个 Docker 进程可能是设置的缓慢点,直到请求在该进程中拆分由集群模块。
那么,一个运行中的 Docker 容器集群能够即时启动和停止它们真的比正确使用 Node.js 的集群模块更重要吗?
如果我有一个容器集群,那么使用 Node.js 的集群模块会给我带来什么吗? api 端点的返回时间不到 0.5 秒(通常要少很多)。
我正在使用 mysql(相信它是一个单一的服务器,目前仅此而已)所以不应该有任何理由使用数据完整性解决方案。
【问题讨论】:
我开始走这条路,我很好奇这对你有什么影响 - 我也很好奇你是使用 pm2 作为下面提到的评论者还是永远使用 pm2 我正在使用 AWS ElasticBeanstalk,因此如果节点命令失败并退出 docker 容器停止并且 EB 由于我的扩展配置而自动启动另一个。到目前为止,不使用集群模块的情况非常好,我们的实例运行 CPU 利用率约为 10%-15%。 【参考方案1】:我认为使用 Docker 时最好的解决方案是尽可能减少每个容器的进程,因为容器是轻量级的;您不希望进程尝试使用多个 CPU。因此,在容器中运行集群不会增加任何价值,并且可能会恶化延迟。
https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef#.9x6j3b8vwChad Robinson 在这里概括地解释了这个想法。
Kubernetes、Rancher、Mesos 和其他容器管理层处理负载平衡。它们在内部提供“调度”(在不同的 CPU 和机器上移动这些 Docker 容器切片以在整个集群中获得良好的使用)和“网络”(对这些容器的入站请求进行负载平衡)层。
更新
我认为值得添加链接Why it is recommended to run only one process in a container?,人们在这里分享他们的想法和经验,但主要来自Jon,有一些有趣的点:
假设您将单一职责(单一进程、功能或关注点)赋予容器:Docker 将此命名为“关注点”是个好主意;)
水平扩展容器更容易。 它可以在不同的项目中重复使用。 与在整个应用程序环境中进行相比,识别问题和排除故障是一件轻而易举的事。此外,日志记录和报告可以更加准确和详细。 可以逐步完全控制升级/降级。 安全性可以应用于特定资源和不同级别。【讨论】:
我不确定这在与 k8s 结合时是否真的可以大规模使用。例如,我们有一个 nodejs 应用程序需要 18 个进程来轻松处理负载峰值。每个容器有 1 个进程,即 18 个 docker 容器有自己的开销。如果 1 进程达到 100% cpu 使用率并且请求开始排队,那么当容器只是 cpu 绑定时,将通过基本运行状况检查将容器检测为“关闭”。容器将重新启动,这将导致更多问题。允许 2 或 3 个进程将降低运行状况检查因一个长时间运行的进程而失败的可能性。 我认为理想的不是一个进程,而是 nodejs Web 应用程序中的一个问题,因为多个子进程控制着您一次可以处理的 请求 的数量。混合 2 个不同的应用程序不是一个好习惯,但多个子进程可以让您的应用程序更加稳定,并允许一个进程失败并重新启动,而无需重新安排整个容器。 嘿@AaronHarun,这是有道理的。我还没去k8s,只在AWS ECS和AWS Fargate上测试过Docker。这里提到了另一个具有相同权衡的讨论。通常没有适合所有问题的完美解决方案,并且取决于您的堆栈、团队和环境,您需要在可能的情况下进行测试后下定决心。 ;) 您应该根据您的考虑在此处添加另一个答案。我会竖起大拇指的。【参考方案2】:我有一个带有 4 个逻辑核心的系统,我在我的机器上以及安装在同一台机器上的 docker 上运行了以下代码。
const numCPUs = require('os').cpus().length;
console.log(numCPUs)
这行在我的机器上打印 4,在 docker 容器内打印 2。这意味着如果我们在 docker 容器中使用集群,则只有 2 个实例会运行。所以 docker 容器看不到与实际机器相同的核心。此外,在启用集群模式的情况下运行 5 个 docker 容器会提供 10 个机器实例,最终由具有 4 个逻辑内核的操作系统内核管理。
所以我认为最好的方法是在集群模式下使用多个 docker 容器实例,并禁用 node.js 集群。这应该会提供最佳性能。
【讨论】:
您确定不是因为您的开发计算机上有默认的 docker 设置吗?您可以手动管理 docker 资源(cpu 内核、内存等)。例如在 Windows 上:docs.docker.com/docker-for-windows【参考方案3】:您必须进行测量才能确定,但我的预感将与节点的集群模块一起运行是值得的。它会以最少的额外开销为您带来更多的 CPU 利用率。无需管理额外的容器(启动、停止、监控)。此外,集群工作人员具有高效的通信机制。在我看来,最合理的演变(不要跳过步骤):
-
1个容器,1个节点进程
1 个容器,多个集群节点工作器
几个容器,每个容器都有几个节点工作人员
【讨论】:
PM2 很受欢迎。它使用集群,并且已经有几个用于 PM2 的 docker 镜像。 我说容器可以访问多核 CPU 是否正确? 是的。如果 docker 不兼容多核,那将是一个巨大的缺点。 我想知道大家对下面这篇文章的看法,这篇文章在 Docker 的上下文中说:“管理和协调自己的资源的进程不再那么有价值。相反,像 Kubernetes、Mesos、和 Cattle 已经普及了这些资源应该在基础设施范围内进行管理的概念。” “在这种类型的环境中,尝试使用过多 CPU 内核的进程可能会成为麻烦制造者。” medium.com/@CodeAndBiscuits/… 我做了一个项目,删除了 node.js 集群模块,只是在容器级别进行了扩展,这很好。它认为“尝试使用过多 CPU 内核”的概念可能具有误导性。即使启用了集群模块,节点也会为每个 CPU 内核启动一个工作进程,即使这样内核也会分配 CPU 负载。一般来说,我同意“Docker 中可能没有集群”,但在特定环境中进行实际测量,集群可能是有益的。以上是关于Docker 容器和 Node.js 集群的主要内容,如果未能解决你的问题,请参考以下文章
node.js docker容器和本地redis服务器之间的连接(127.0.0.1)[重复]
docker+mysql(8.0.15)+node.js(hapi.js)构建容器(命令行)