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 開始分析


發佈了112 篇原創文章 · 獲贊 37 · 訪問量 68萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章