接着上文,上文利用提到程序利用
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會找到合適的對象去處理。