egg框架启动过程和核心入口(图解)

egg启动分为单进程启动和多进程启动两种方式

部分源码:

/**
 * Start egg application with cluster mode
 * @since 1.0.0
 */
exports.startCluster = require('egg-cluster').startCluster;

/**
 * Start egg application with single process mode
 * @since 1.0.0
 */
exports.start = require('./lib/start');

单进程启动:

module.exports = async (options = {}) => {
  if (!options.ignoreWarning) {
    console.warn('single process mode is still in experiment, please don\'t use it in production environment');
  }

  options.baseDir = options.baseDir || process.cwd();
  options.mode = 'single';

  // get agent from options.framework and package.egg.framework
  if (!options.framework) {
    try {
      options.framework = require(path.join(options.baseDir, 'package.json')).egg.framework;
    } catch (_) {
      // ignore
    }
  }
  let Agent;
  let Application;
  if (options.framework) {
    Agent = require(options.framework).Agent;
    Application = require(options.framework).Application;
  } else {
    Application = require('./application');
    Agent = require('./agent');
  }

  const agent = new Agent(Object.assign({}, options));
  await agent.ready();
  const application = new Application(Object.assign({}, options));
  application.agent = agent;
  agent.application = application;
  await application.ready();

  // emit egg-ready message in agent and application
  application.messenger.broadcast('egg-ready');

  return application;
};

可以看出直接会调用 new Application(Object.assign({}, options));

多进程启动:

总括:启动过程的分析是找到总的入口文件:eggCore下的Loader是整个egg框架的入口

egg在koa框架之上进行了高度集成,进行了统一规范,在写项目的过程中,很难看出egg是怎样工作的。也就无法了解到egg的插件机制,扩展机制等是如何和koa集成。作为一名开发者仅仅掌握配置使用egg是远远不够的,本文就egg的启动过程进行了梳理,将egg的启动过程总结为一张流程图。

在egg启动过程中,主要是依赖egg-bin,egg-bin有依赖了common-bin,common-bin中又依赖了yargs,yargs-parser,有兴趣的可以自行去看yargs的文档,本文不做详细介绍。流程图如下:

简易流程:

从package.json可以看到执行npm tun dev会执行egg-bin dev

1,进到egg-bin中,会创建egg-bin实例,EggBIn实例继承自CommonBin实例,

2,接下来会执行CommonBin的load方法,将egg-bin中cmd文件夹下的启动文件放入CommonBin实例的[COMMAND](map集合)中

3,再根据命令行参数拿到对应的启动文件,执行启动文件的run方法,找到egg-cluster

4,执行egg-cluster的master方法,创建Master实例,开启App_worker子进程,Agent_worker子进程

5,App_worker子进程创建EggCore实例,并创建Loader,Lifecicle实例,Loader是egg把所有文件串起来的入口

 

详细流程图:里面有许多node的包,想研究的同学可以自行研究

 

说明:

1,这里有一个难点,this.serverBin指向了egg-bin的lib/start-cluster脚本,其中的options.framework参数从何而来,有点绕,这里的process.argv[2]正是之前cp.fork(modulePath, args, options)子进程启动时传递的参数,如果是dev,当前的process.argv[2]的值是这样的:

{
	"typescript": false,
	"declarations": true,
	"workers": 1,
	"baseDir": "项目根路径",
	"port": 7002,
	"framework": "项目根路径/node_modules/egg"
}

2,图中master进程启动时,会通过cfork包启动app_worker进程,cfork会在开启子进程时,传入执行文件路径,执行文件参数, agent_work通过child_process.fork实现

部分源码:egg-cluster包下文件夹lib/utils/master.js

agent_work进程

const agentWorker = childprocess.fork(this.getAgentWorkerFile(), args, opt);

app_work进程

   cfork({
      exec: this.getAppWorkerFile(),
      args,
      silent: false,
      count: this.options.workers,
      // don't refork in local env
      refork: this.isProduction,
      windowsHide: process.platform === 'win32',
    });

总结:这里主要介绍了egg的启动过程,egg的核心加载流程后续介绍

参考:https://juejin.im/post/5be92cc95188251fd925d49b

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值