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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章