pomelo源碼分析(五)

接着上一章節,上一章節主要是介紹Master Server的初始化,接下來就是初始化後的啓動

lib/master/master.js

var Server = function(app) {
	this.app = app;
	this.masterInfo = app.get('master');
	this.registered = {};

	this.masterConsole = admin.createMasterConsole({
		port: this.masterInfo.port
	});
};


Server.prototype.start = function(cb) {
	registerDefaultModules(this.app);   //註冊默認模塊
	loadModules(this.app, this.masterConsole); //執行模塊

	var self = this;
	this.masterConsole.start(function(err) {
		if(err) {
			cb(err);
			return;
		}
		starter.runServers(self.app);
		cb();
	});
	
	this.masterConsole.on('register', function(record) {
		logger.debug('[master] new register connection: %j, %j', record.id, record.type);
		self.registered[record.id] = record;
		if(checkRegistered(self)) {
			logger.info('[master] all servers have started and notify after start now...');
			self.masterConsole.agent.notifyAll(AfterStart.moduleId);
		}
	});

	this.masterConsole.on('disconnect', function(id, type, reason) {
		crashLogger.info(util.format('[%s],[%s],[%s],[%s]', type, id, Date.now(), reason || 'disconnect'));
	});
};

registerDefaultModules

/**
 * Append the default system admin modules
 */
var registerDefaultModules = function(app) {
	app.registerAdmin(require('../modules/console'), {app: app, starter: starter});
	if(app.enabled('systemMonitor')) {  //啓動系統檢測
		app.registerAdmin(admin.modules.systemInfo);  //登記系統信息模塊
		app.registerAdmin(admin.modules.nodeInfo);    //登記節點模塊信息
		app.registerAdmin(admin.modules.monitorLog,{path: pathUtil.getLogPath(app.getBase())});  //登記日誌模塊信息
		app.registerAdmin(admin.modules.scripts, {app: app, path: pathUtil.getScriptPath(app.getBase())});
		app.registerAdmin(admin.modules.profiler, {isMaster: true});  
	}
};

registerAdmin作用,傳輸三個參數1.模塊名字(參數可選),2.模塊對象或工廠方法 3.模塊參數,登記在'__module__'內存中

登記模塊完成後,通過loadModules加載剛纔註冊的模塊。

/**
 * Load admin modules
 */
var loadModules = function(app, consoleService) {
	// load app register modules 
	var modules = app.get('__modules__');

	if(!modules) {
		return;
	}

	var record, moduleId, module;
	for(var i=0, l=modules.length; i<l; i++){
		record = modules[i];
		if(typeof record.module === 'function') {  //檢查模塊是否有參數,有參數則傳入參數
			module = record.module(record.opts);
		} else {
			module = record.module;
		}

		moduleId = record.moduleId || module.moduleId;

		if(!moduleId) {
			logger.warn('ignore an uname module.');
			continue;
		}

		consoleService.register(moduleId, module);	//爲consoleService 註冊模塊到對象裏面
	}
};

ConsoleService.prototype.register = function(moduleId, module) {
	this.modules[moduleId] = registerRecord(this, moduleId, module);
};
註冊所有模塊後,執行start

	this.masterConsole.start(function(err) {
		if(err) {
			cb(err);
			return;
		}
		starter.runServers(self.app);
		cb();
	});
實際執行代碼
/**
 * start master or monitor 
 *
 * @param {Function} cb callback function
 * @api public
 */
ConsoleService.prototype.start = function(cb) {
	if(this.master) {  //mater啓動配置
		this.agent.listen(this.port);  //實際調用的是masterAgent.listen
		exportEvent(this, this.agent, 'register');    //利用masterAgent 監聽'register'事件,並返回到當前事件
		exportEvent(this, this.agent, 'disconnect'); //利用masterAgent 監聽'disconnect'事件,並返回到當前事件
		process.nextTick(function() {
			utils.invokeCallback(cb);  //檢查全局函數裏面,是否存在回調函數
		});
	} else {  //monitor啓動配置
		logger.info('try to connect master: %j, %j, %j', this.type, this.host, this.port);
		this.agent.connect(this.port, this.host, cb);
		exportEvent(this, this.agent, 'close');
	}

	exportEvent(this, this.agent, 'error');

	for(var mid in this.modules) {
		this.enable(mid);  //使能所有剛纔註冊的模塊
	}
};

根據application所配置的選項,利用命令啓動服務器

/**
 * Run all servers
 *
 * @param {Object} app current application  context
 * @return {Void}
 */
starter.runServers = function (app) {
	var servers = app.getServers();
	for (var serverId in servers) {
		this.run(app, servers[serverId]);
	}
};

如果是遠端的服務器,則利用ssh命令來啓動遠端的服務器

/**
 * Run server
 * 
 * @param {Object} app current application context
 * @param {Object} server
 * @return {Void}
 */
starter.run = function (app, server) {
	var cmd = util.format('cd %s && node ', app.getBase());
	var arg = server.args;
	if (arg !== undefined) {
		cmd += arg;
	}
	this.env = app.get('env');
	cmd+=util.format(' %s env=%s serverType=%s serverId=%s', app.get('main'), this.env, server.serverType, server.id);
	if (isLocal(server.host)) {
		starter.localrun(cmd);
	} else {
		starter.sshrun(cmd, server.host);
	}
};

今天就這樣結束了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章