pomelo源码分析(四)

接着上文,上文利用提到程序利用

this._optComponents('start', function(err) {  
    self.state = STATE_START;  
    utils.invokeCallback(cb, err);  
  });  

发送命令让刚配置好的服务器模块,执行start命令,现在我们开始分析master.start();

lib/components/master.js

var Master = require('../master/master');

var pro = Component.prototype;

/**
 * Component lifecycle function
 *
 * @param  {Function} cb
 * @return {Void}
 */
pro.start = function (cb) {
  this.master.start(cb);
};

var Master = require('../master/master');

初始化Master模块

module.exports = Server;

var Server = function(app) {
  this.app = app;
  this.masterInfo = app.get('master');  //获取master的服务器信息,前文有介绍,从master.json文件里面 ,defaultConfiguration函数里
  this.registered = {};

  this.masterConsole = admin.createMasterConsole({ //创建一个MasterConsole
    port: this.masterInfo.port
  });
};

adminConsole 有三种角色,分别是 master,monitor,client
  • master : 运行在master进程中,监听端口等待monitor和client的连接。主要负责维护所有已注册的连接,消息路由和处理,以及缓存服务器集群状态信息。
  • monitor : 运行在各个需要监控的服务器进程中(包括master进程)。启动后连接并注册到master,主要负责收集被监控的进程信息,向master汇报。
  • client : 运行在admin console的web页面。启动后连接并注册到master。主要负责响应用户操作和呈现master返回结果。

其实,此代码写得是masterconsole.主要负责维护所有已注册的连接,消息路由和处理,以及缓冲服务器集群的状态信息

pomelo/node_modules/pomelo-admin/lib/consoleServer.js

/**
 * Create master ConsoleService
 * 
 * @param {Object} opts construct parameter
 *                      opts.port {String | Number} listen port for master console
 */
module.exports.createMasterConsole = function(opts) {
	opts = opts || {};
	opts.master = true;  //标记为master服务器
	return new ConsoleService(opts);  //根据opts.master 的标记来决定初始化master服务器或monitor服务器,创建consoleService,并返回
};

创建consoleService对象

/**
 * ConsoleService Constructor
 * 
 * @class ConsoleService
 * @constructor
 * @param {Object} opts construct parameter
 *                      opts.type {String} server type, 'master', 'connector', etc.
 *                      opts.id {String} server id
 *                      opts.host {String} (monitor only) master server host
 *                      opts.port {String | Number} listen port for master or master port for monitor
 *                      opts.master {Boolean} current service is master or monitor
 * @api public
 */
var ConsoleService = function(opts) {
	EventEmitter.call(this);  //ConsoleService继承EventEmitter 方法
	this.port = opts.port;  //设置master服务器端口
	this.values = {};
	this.master = opts.master;  //服务器类型标记,true为master ,其余为monitor

	this.modules = {};

	if(this.master) {
		this.agent = new MasterAgent(this);  //创建MasterAgent 对象
	} else {
		this.type = opts.type;
		this.id = opts.id;
		this.host = opts.host;
		this.agent = new MonitorAgent({      //创建MonitorAgent对象
			consoleService: this, 
			id: this.id, 
			type: this.type
		});
	}
};

util.inherits(ConsoleService, EventEmitter); //在ConsoleService下,创建super_ 属性 指向EventEmitter

这里涉及的概念主要有2个,第一个consoleService继承node.js的事件方法,第二个创建MasterAgent或MonitorAgent。

第一,consoleService继承node.js的事件方法

EventEmitter.call(this);  //ConsoleService继承EventEmitter 方法 ,可以 使用 this.emit方法 和 一些事件的监听,如下

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

util.inherits() node.js的util提供的方法 http://docs.cnodejs.net/cman/util.html#util_

util.inherits(constructor, superConstructor)
Inherit the prototype methods from one constructor into another. The prototype of constructor will be set to a new object created from superConstructor.
将一个构造函数的原型方法继承到另一个构造函数中。constructor构造函数的原型将被设置为使用superConstructor构造函数所创建的一个新对象。
As an additional convenience, superConstructor will be accessible through the constructor.super_ property.
此方法带来的额外的好处是,可以通过constructor.super_属性来访问superConstructor构造函数。

var util = require("util");
var events = require("events");

function MyStream() {
    events.EventEmitter.call(this);
}

util.inherits(MyStream, events.EventEmitter);

MyStream.prototype.write = function(data) {
    this.emit("data", data);
}

var stream = new MyStream();

console.log(stream instanceof events.EventEmitter); // true
console.log(MyStream.super_ === events.EventEmitter); // true

stream.on("data", function(data) {
    console.log('Received data: "' + data + '"');
})
stream.write("It works!"); // Received data: "It works!"

第二,MasterAgent和MonitorAgent作用

  • consoleService,是整个监控模块的总入口,master和monitor上都需要创建。各个进程向consoleService注册各自的module。ConsoleService根据当前服务器类型,创建底层的agent实例,并负责agent的启动和关闭。consoleService同时也充当了map的角色,缓存收集到的状态信息。
  • masterAgent,在master进程中启动,负责底层网络通讯相关工作。如:监听端口,接收monitor和client连接,分组维护这些连接以及将消息推送给指定的接收者等。
  • monitorAgent,在各个需要监控进程中启动(包括master进程)。启动后连接并注册到masterAgent,负责与masterAgent之间的通讯。
  • module,监控模块接口,实现监控相关的具体逻辑。定义三个回调接口,分别对应于master,monitor和client上的逻辑。

接下来,我们继续看ConsoleService 里会初始化一个MasterAgent

MasterAgent

if(this.master) {
		this.agent = new MasterAgent(this);
	}

var MasterAgent = function(consoleService) {
	EventEmitter.call(this);
	this.consoleService = consoleService;
	this.server = null;
	this.idMap = {};
	this.typeMap = {};
	this.clients = {};
	this.reqId = 1;
	this.callbacks = {};
	this.state = ST_INITED;
};

MonitorAgent

	this.type = opts.type;
	this.id = opts.id;
	this.host = opts.host;
	this.agent = new MonitorAgent({
		consoleService: this, 
		id: this.id, 
		type: this.type
	});

var MonitorAgent = function(opts) {
	EventEmitter.call(this);
	this.consoleService = opts.consoleService;
	this.id = opts.id;
	this.type = opts.type;
	this.socket = null;
	this.reqId = 1;
	this.callbacks = {};
	this.state = ST_INITED;
};
总结一下流程,代码需要执行master.start()的时候,需要对master进行初始化,初始化的过程中,会初始化createMasterConsole -> 初始化ConsoleService并返回-> 初始化MasterAgent。ConsoleService相当于agent的总代理,我们有事情就找ConsoleService,consoleservice会找到合适的对象去处理。
发布了112 篇原创文章 · 获赞 37 · 访问量 68万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章