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);
	}
};

今天就这样结束了。


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