pomelo源码分析(三)

app.js

// start app
app.start();
lib/application.js
/**
 * Start application. It would load the default components and start all the loaded components.
 *
 * @param  {Function} cb callback function
 *
 * @memberOf Application
 */
Application.start = function(cb) {
  if(this.state > STATE_INITED) {
    utils.invokeCallback(cb, new Error('application has already start.'));
    return;
  }
  this.loadDefaultComponents();
  var self = this;
  this._optComponents('start', function(err) {
    self.state = STATE_START;
    utils.invokeCallback(cb, err);
  });
};
Application状态注释,当application进入初始化的时候调用 loadDefaultComponents 和 _optComponents 等

/**
 * Application states
 */
var STATE_INITED  = 1;  // app has inited
var STATE_START = 2;    // app start
var STATE_STARTED = 3;  // app has started
var STATE_STOPED  = 4;  // app has stoped
加载默认的application模块
/**
 * Load default components for application.
 *
 * @api private
 */
Application.loadDefaultComponents = function(){
  var pomelo = require('./pomelo');

  if (this.serverType === 'master') {
    this.load(pomelo.master, this.get('masterConfig'));
  } else {
    this.load(pomelo.proxy, this.get('proxyConfig'));
    if(this.getServerById(this.get('serverId')).port) {
      this.load(pomelo.remote, this.get('remoteConfig'));
    }
    if(this.isFrontend()) {
      this.load(pomelo.connection, this.get('connectionConfig'));
      this.load(pomelo.connector, this.get('connectorConfig'));
      this.load(pomelo.session, this.get('sessionConfig'));
    } else {
      this.load(pomelo.localSession, this.get('localSessionConfig'));
    }
    this.load(pomelo.channel, this.get('channelConfig'));
    this.load(pomelo.server, this.get('serverConfig'));
  }
  this.load(pomelo.monitor, this);
};
根据配置文件来加载对应的服务器,让我们看看load函数

/**
 * Load component
 *
 * @param  {String} name    (optional) name of the component
 * @param  {Object} component component instance or factory function of the component
 * @param  {[type]} opts    (optional) construct parameters for the factory function
 * @return {Object}     app instance for chain invoke
 *
 * @memberOf Application
 */
Application.load = function(name, component, opts) {
  if(typeof name !== 'string') {
    opts = component;
    component = name;
    name = null;
    if(typeof component.name === 'string') {  //确认参数是名字还是函数
      name = component.name;
    }
  }

  if(typeof component === 'function') {  //确认是函数后,执行其对应的构造函数,如果存入的参数是Mater,那就相当于执行master(this.opts) -> this.master = new Master(app)
    component = component(this, opts);
  }

  if(!component) {
    // maybe some component no need to join the components management  
    logger.info('load empty component');
    return this;
  }

  if(!name && typeof component.name === 'string') {
    name = component.name;
  }

  if(name && this.components[name]) {
    // ignore duplicat component
    logger.warn('ignore duplicate component: %j', name);
    return;
  }

  this.loaded.push(component);
  if(name) {
    // components with a name would get by name throught app.components later.  
    this.components[name] = component;  //执行完模块的构造函数后,将实例对象存放到components里,如master,即new Master(app)返回的实例

  }

  return this;
};

初始化默认加载模块的列表汇总
  • master: master组件主要负责启动master服务器。
  • monitor: monitor组件主要负责启动各个服务器的monitor服务,该服务负责收集服务器的信息并定期向master进行消息推送,保持master与各个服务器的心跳连接。
  • proxy: proxy组件主要负责生成服务器rpc客户端,由于系统中存在多个服务器进程,不同服务器进程之间相互通信需要通过rpc调用(master服务器除外)。
  • handler:handler组件主要负责加载前端服务器中的handler目录下的文件。
  • filter: filter组件主要负责加载服务器请求的filter服务,包括rpc调用前的filter及rpc调用后的filter。
  • remote: remote组件主要负责加载后端服务器的服务并生成服务器rpc服务端。
  • server:server组件主要负责启动所有服务器的用户请求处理服务。
  • connector: connector组件主要负责启动前端服务器的session服务和接收用户请求。
  • sync: sync组件主要负责启动数据同步模块并对外提供数据同步功能。
  • connection: connection组件主要负责启动用户连接信息的统计服务。
从已加载模块里面,批量执行对应模块的方法,根据上面的代码,传入的参数是‘start',即每一个模块都执行start,如master,即执行master.start()

/**
 * Apply command to loaded components.
 * This method would invoke the component {method} in series.
 * Any component {method} return err, it would return err directly.
 *
 * @param  {String}   method component lifecycle method name, such as: start, afterStart, stop
 * @param  {Function} cb
 * @api private
 */
Application._optComponents = function(method, cb) {
  var i = 0;
  async.forEachSeries(this.loaded, function(comp, done) {  //async 异步里面同步执行模块,forEachSeries,即逐个模块执行start,同步执行,如master,即执行master.start
    i++;
    if(typeof comp[method] === 'function') {  //判断是否存在method里的方法,如果存在,即执行
      comp[method](done);
    } else {
      done();
    }
  }, function(err) {
    if(err) {
      logger.error('[pomelo application] fail to operate component, method:%s, err:' + err.stack, method);
    }
    cb(err);
  });
};


async模块的git:https://github.com/caolan/async

这篇就介绍完毕,通过loadDefaultComponents 函数加载默认模块,master是服务器最基本的模块,下篇我们将从 master.start 开始分析


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值