egg多进程

Worker 是 Egg 中对于多进程模型的具体实现。因此,在介绍 Worker 前,我们先浅谈一下什么是多进程模型。

CPU、操作系统和进程

       CPU 是计算机中的计算单元,其能力和行为也非常单纯:接收到指令进行计算,将计算结果返回。而并不关注计算谁,由谁来进行调度。
       操作系统 用于调度计算资源,每个操作系统都会遵循一定的规则,来调度分配,谁当前能够得到计算机的计算资源,也就是在当前的这一刻,CPU 来计算哪个程序分配的什么任务。
       应用程序 是一系列用于完成某种特定功能的代码段集合,在尚未执行时,存储于计算机的磁盘之中。当开始运行时,则会加载到内存之中。
       进程 则是表示一个正在运行中的应用程序

image


       上图是一个 CPU 与进程之间交互的模拟示例。
       假设这里是一个业务柜台,我们开设了三条通道以便表示正在运行中的三个程序(进程)。每一个通道(进程)中,都可能会有数个任务等待被CPU运算执行结果。我们假设CPU是一个头脑非常好的业务人员,业务熟练度非常高,办事效率极快。但依然有一个问题就是:同一时间,一个CPU只能处理一件事
       我们假设CPU业务员所坐的柜台就是一个操作系统,柜台外只要有人说话,操作系统就会做出如下反应:将CUP所坐的椅子移动到另一个更紧急的需要处理的进程位置,来处理相应的业务。而在移动之前,CPU还需要做一些事——保存当前进程的执行状态( 比如进程1的第一个用户,他的业务办理到了哪一步 ),以便于下一次该进程再次被CPU调度时可以继续处理运算。而在移动到另一个位置之后,CPU业务员首先会打开一个记录簿,看看这个位置的业务处理到了哪一步,然后接着进行处理。
       描述的过程是缓慢的,幸好我们的CPU执行的速度极快,因此我们看到的仿佛是所有的程序正在同时运行。例如我们可以一边听歌一边写文档,而两个进程不会互相干扰。

 

进程和线程

       进程(process) 表示在内存中正在运行的一个程序,而线程(thread)则表示当前进程中的最小处理(调度)单元

image


       CPU 真正需要运算的数据,是由线程给与的,我们可以认为线程中包含了程序运行过程中的每一个行为、步骤,而线程本身,就相当于是上图所示的一个通道。在一个进程中,至少会有一个线程真正的在与CPU打交道。当然,进程中也允许拥有多个线程,也就是我们常说的多线程
       多线程模型解决的最大的问题,就是它允许每个线程共享进程中的资源。并且CPU在同一进程中的线程之间调度的过程中,减少了打开和保存进程上下文的开销。假设上述的业务模型中,每一个进程都表示一个需要办理业务的公司( 公司1 对应进程1 ,公司2对应进程2 )。此时在公司2的两个通道间切换CPU业务员的调度时,需要保存的信息就少了很多——既然他们都来自于一个公司,那么在办理业务方面就有很多一致的地方。比如填写的表单、发票头等等。
       多线程模型在获取CPU调度概率方面也有一定优势,更多人喊话当然得到回应的几率会增大(笑哭)。但如果当前运行环境只是基于单核CPU时,实际上在提升性能方面表现的优势非常之小。
       与此同时,多线程模型还有着诸多应用隐患:假设图中进程2的两名男子都是接到了任务:查询公司今天的入账,如果在100-150万之间,则取款50万。此时,男子A先查询并取钱,假设这一天公司入账是120万,符合条件。那么CPU应当告知男子A你可以取50万。但在此时男子B突然开口喊话,并得到了操作系统的调度(此时男子A还没取款,账户依然是120万)。男子B需要完成同样的业务,CPU经过运算得知当前账户依然是120万,也允许男子B取款...男子B取款结束后,又被调度至男子A同样取款50万。像这样的多个线程执行同一个任务的过程中,可能会引发的逻辑错误违背了可重入性(即函数可以由多于一个任务并发使用,而不必担心数据错误),当然可以以其他的机制尽可能规避多线程下导致的线程安全问题,但这也着实提升了应用的复杂度。

 

单线程多进程模型

node.js 继承了 JavaScript 以单线程作为主线程的风格,与进程中开辟多线程而言具备以下优势:

  • 多线程占用内存高,单线程占用内存低;
  • 多线程间切换使得CPU开销大;
  • 多线程由内存同步开销;
  • 编写单线程程序更加简单;
  • 线程安全;

但是,相应的也拥有以下劣势:

  • CPU密集型任务占用CPU时间长;
  • 无法利用CPU的多核;
  • 单线程抛出异常使得程序停止;

 

image


       现代的计算机,基本都是基于多核的CPU。在计算机中运行单进程单线程的应用程序时,最大的问题便是无法利用多核导致CPU空闲,以及当线程阻塞时,整个任务停滞无法继续
       因此,Egg 为了尽可能的压榨CPU资源,使用单线程多进程模型,利用 nodejs 中的 cluster 模块,根据 CPU 核数创建相应的子进程。这样的子进程也被称之为是工作进程——Worker。因此,处理方式就变成了:

image


以此确保CPU的最大利用率。并且,程序运行的过程中,如果出现了某一个进程挂掉,也不会影响整体应用程序奔溃,因为其他进程也可以调度处理相应的问题。

 

Master 和 Worker

       假设我们的应用运行在一个提供了四核CPU的系统中,Egg 会帮我们建立如下结构:

image


Master 进程负责启动其他的 Worker ,并且在 Worker 出现问题时对其进行重启操作,我们可以认为他是一个守护进程。而具体应用中的业务,Master 并不执行。
Worker 进程是具体的工作进程,我们之前的 APP 相对而言就是一个 WorkerMaster会根据具体的 CPU 核数进行判断,究竟 fork 几个 Worker 来榨干服务器CPU。
 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值