YSS

Write Less & Do More

多进程启动 vs 单进程启动

前言

本来是在毫无顾虑的写着一篇 支持多进程启动 的 RFC。但是张导的一个评论给了我一个启发性的疑问。

就是在 k8s 模式下我们能不能用单进程方式去做。

在我以前的认知里,单进程的模式下总是会存在很多的问题,比如:

  1. 当前进程挂了整个这台机器的服务就挂了。
  2. 还有资源利用不充分的问题,就是单台服务的监控类的占比总是固定的,在多进程模式下对应的这部分处理的占比只会趋于更小。比如之前 service 上新建一个机器,你申请的是 4G 内存,但直接分配的是 5G 内存,现在如果换成申请 1G 内存,那就意味着分配的是 2G,相当于系统资源占了总资源的 50%。

目标

确定在 k8s 架构下的 Node.js Server 启动模式。

方案

方案描述

  1. 多进程启动指的是,基于 Cluster 模块下的 一个 Master + 多个 Worker 形式。这种形式主要是为了充分的利用 CPU。
  2. 单进程启动指的是,只有一个 Master 进程,它直接接收和响应请求,这个时候只需要 1 个 CPU 即可。

方案对比

多进程启动 单进程启动  
运行成本 整体比较复杂,Master 需要统一维护和管理 Worker。需要一个单独的模块来处理这部分事务。 只需要关注自己。
监控类工具 需要额外的处理,主要的表现就是需要在 Master 统一收集后再处理。 只需要关注自己。
日志类工具 需要额外多打印一个进程 ID,就是时序上看会比较乱。 独立占用一个文件输出,日志比较规律。
稳定性上 一般需要有一个额外的守护进程来守护 Master 进程,然后 Master 进程本身还需要实现一些重启逻辑来处理 Worker 进程的崩溃问题。 可以有两种方式:一种是增加一个守护进程。第二种是交给运维层面去做,遇到崩溃就重启整个 Docker。具体的花销可能会比直接 Master 管理下的进程重启更大一些。
资源成本 跟基础架构同学简单了解了,资源成本上几乎没有多余的消耗。原因在于 k8s 下,不是去启动一个虚拟机而是一组进程的 group。然后对于容器平台来讲,资源的粒度越小,调度的空间越高  
部署成本 跟基础架构同学了解到目前部署上采用的是 k8s 默认的 deployment 的 rolling 策略。先启动 30% 新的容器,做探活,如果成功,就使 30% 的容器进入 shutdown 状态。相当于用新容器部署,老容器逐步下线。所以部署成本几乎无差异。  

Kubernets 的理念

当然,最终我们还是需要放到 K8S 这个大环境下去考量。

K8S 本身是一个管理容器化应用的开源系统。

最底层的一个概念是 Pod,Pod 是可以在 Kubernetes 中创建和管理的最小的可部署的计算单元。

一个 Pod 由一个或多个 Container 组成。

而我们的每个应用其实都是一个 Container。

对于 Container 的,K8S 的定义是它是一个可重复的,包含依赖环境在内的标准。

然后,Pod 之上是有一个 Service 来负责统一对外暴露服务接口,屏蔽服务细节,以及做流量负载均衡。

那么,整体看,在 K8S 容器下使用单进程模式,不失为一个非常不错的方式。

最后

整体看,多进程主要是在解决资源浪费问题,但由此也带来了更高的复杂性。

单进程就使得一切都变得更简单。