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'));
});
};
接上一章
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'));
});
通過masterConsole,調用consoleService,consoleService調用masterAgent監聽register事件,監聽的具體函數如下
/**
* master listen to a port and handle register and request
*
* @param {String} port
* @api public
*/
MasterAgent.prototype.listen = function(port) {
if(this.state > ST_INITED) {
logger.error('master agent has started or closed.');
return;
}
this.state = ST_STARTED;
this.server = sio.listen(port); //io.socket 監聽port
this.server.set('log level', 0);
var self = this;
this.server.server.on('error', function(err) {
self.emit('error', err); //對MasterAgent 發送事件信息
});
this.server.sockets.on('connection', function(socket) {
var id, type, registered;
socket.on('register', function(msg) {
// register a new connection
if(msg && msg.type) {
if(msg.type === 'client') {
// client connection not join the map
if(!msg.id) {
// client should has a client id
return;
}
if(self.clients[msg.id]) {
socket.emit('register', {code: protocol.PRO_FAIL, msg: 'id has been registered. id:' + msg.id});
return;
}
addConnection(self, msg.id, msg.type, msg.pid, socket);
id = msg.id;
type = msg.type;
registered = true;
socket.emit('register', {code: protocol.PRO_OK, msg: 'ok'});
return;
}
if(msg.id) {
// if is a normal server
if(self.idMap[msg.id]) {
socket.emit('register', {code: protocol.PRO_FAIL, msg: 'id has been registered. id:' + msg.id});
return;
}
var record = addConnection(self, msg.id, msg.type, msg.pid, socket);
id = msg.id;
type = msg.type;
registered = true;
socket.emit('register', {code: protocol.PRO_OK, msg: 'ok'});
self.emit('register', record);
}
}
}); // end of on 'register'
// message from monitor
socket.on('monitor', function(msg) {
if(!registered) {
// not register yet, ignore any message
return;
}
if(type === TYPE_CLIENT) {
logger.error('invalid message to monitor, but current connect type is client.');
return;
}
msg = protocol.parse(msg);
if(msg.respId) {
// a response from monitor
var cb = self.callbacks[msg.respId];
if(!cb) {
logger.warn('unknown resp id:' + msg.respId);
return;
}
delete self.callbacks[msg.respId];
utils.invokeCallback(cb, msg.error, msg.body);
return;
}
// a request or a notify from monitor
self.consoleService.execute(msg.moduleId, 'masterHandler', msg.body, function(err, res) {
if(protocol.isRequest(msg)) {
var resp = protocol.composeResponse(msg, err, res);
if(resp) {
socket.emit('monitor', resp);
}
} else {
//notify should not have a callback
logger.warn('notify should not have a callback.');
}
});
}); // end of on 'monitor'
// message from client
socket.on('client', function(msg) {
if(!registered) {
// not register yet, ignore any message
return;
}
if(type !== TYPE_CLIENT) {
logger.error('invalid message to client, but current connect type is ' + type);
return;
}
msg = protocol.parse(msg);
// a request or a notify from client
// and client should not have any response to master for master would not request anything from client
self.consoleService.execute(msg.moduleId, 'clientHandler', msg.body, function(err, res) {
if(protocol.isRequest(msg)) {
var resp = protocol.composeResponse(msg, err, res);
if(resp) {
socket.emit('client', resp);
}
} else {
//notify should not have a callback
logger.warn('notify should not have a callback.');
}
});
}); // end of on 'client'
socket.on('disconnect', function() {
removeConnection(self, id, type);
self.emit('disconnect', id, type);
});
socket.on('error', function(err) {
self.emit('error', id, type, err);
});
}); // end of on 'connection'
}; // end of listen
masterAgent 和 monitorAgent主要任務就是負責監聽端口傳入的各種事件,下圖是截取http://golanger.cn的圖,圖裏面畫對次過程描述得非常清晰
master 捕捉 'register‘事件,等待MasterAgent發出'register’事件信號的時候,執行以下代碼
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);
}
});
執行 self.masterConsole.agent.notifyAll(AfterStart.moduleId);
通知所有模塊都執行AftersStart,通知所有模塊都執行afterstart,到這裏爲止,pomelo的啓動流程基本結束
我們看看官方是怎麼定義這一些列的啓動過程
組件可以根據需要,提供不同的生命週期接口,pomelo框架會在生命週期的各個階段觸發相應的回調。組件的生命週期接口類型如下:
- start(cb) 服務器啓動回調。在當前服務器啓動過程中,會按註冊順序觸發各組件的這個接口。組件啓動完畢後,需要調用cb函數通知框架執行後續流程。
- afterStart(cb) 服務器啓動完畢回調。當pomelo管理下的所有服務器進程都啓動完成後會觸發這個接口。一些需要等待全局就緒的工作可以放到這裏來完成。
- stop(force, cb) 服務器關閉回調。在服務器關閉期間,會根據註冊順序的逆序來觸發這個回調接口,主要用來通知各個組件保存各自的數據和釋放資源。force表示是否要強制關閉。操作完畢後,同樣需要調用cb函數來繼續後續流程。
最後,截取我的啓動日誌作爲文章的結尾
"C:\Program Files\nodejs\node.exe" chatofpomelo\game-server\app.js
[2013-03-23 11:47:43.609] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\application.js - app.init invoked #啓動mater 第一個服務器
[2013-03-23 11:47:43.982] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\application.js - application inited: "master-server-1"
[2013-03-23 11:47:45.075] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:45.076] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\master\starter.js - Executing cd #通過mater裏面,runServer命令啓動採用cmd命令的方式啓動多個相關服務器組
D:\src\pomelo\chatofpomelo\game-server && node D:\src\pomelo\chatofpomelo\game-server\app.js env=development serverType=connector serverId=connector-server-1 locally
[2013-03-23 11:47:45.221] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\master\starter.js - Executing cd D:\src\pomelo\chatofpomelo\game-server && node D:\src\pomelo\chatofpomelo\game-server\app.js env=development serverType=connector serverId=connector-server-2 locally
[2013-03-23 11:47:45.239] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\master\starter.js - Executing cd D:\src\pomelo\chatofpomelo\game-server && node D:\src\pomelo\chatofpomelo\game-server\app.js env=development serverType=connector serverId=connector-server-3 locally
[2013-03-23 11:47:45.397] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\master\starter.js - Executing cd D:\src\pomelo\chatofpomelo\game-server && node D:\src\pomelo\chatofpomelo\game-server\app.js env=development serverType=chat serverId=chat-server-1 locally
[2013-03-23 11:47:45.468] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\master\starter.js - Executing cd D:\src\pomelo\chatofpomelo\game-server && node D:\src\pomelo\chatofpomelo\game-server\app.js env=development serverType=chat serverId=chat-server-2 locally
[2013-03-23 11:47:45.552] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\master\starter.js - Executing cd D:\src\pomelo\chatofpomelo\game-server && node D:\src\pomelo\chatofpomelo\game-server\app.js env=development serverType=chat serverId=chat-server-3 locally
[2013-03-23 11:47:45.647] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\master\starter.js - Executing cd D:\src\pomelo\chatofpomelo\game-server && node D:\src\pomelo\chatofpomelo\game-server\app.js env=development serverType=gate serverId=gate-server-1 locally
[2013-03-23 11:47:45.750] [INFO] \chatofpomelo\game-server\node_modules\pomelo\node_modules\pomelo-admin\lib\consoleService.js - try to connect master: "master", "127.0.0.1", 3005
[2013-03-23 11:47:45.970] [INFO] console - [2013-03-23 11:47:45.606] [INFO] \node_modules\pomelo\lib\application.js - app.init invoked #開始執行初始化對應的服務器
[2013-03-23 11:47:45.970] [INFO] console - [2013-03-23 11:47:45.895] [INFO] \node_modules\pomelo\lib\application.js - app.init invoked
[2013-03-23 11:47:46.791] [INFO] console - [2013-03-23 11:47:45.980] [INFO] \node_modules\pomelo\lib\application.js - app.init invoked
[2013-03-23 11:47:46.791] [INFO] console - [2013-03-23 11:47:46.078] [INFO] \node_modules\pomelo\lib\application.js - app.init invoked
[2013-03-23 11:47:46.792] [INFO] console - [2013-03-23 11:47:46.139] [INFO] \node_modules\pomelo\lib\application.js - app.init invoked
[2013-03-23 11:47:46.792] [INFO] console - [2013-03-23 11:47:46.294] [INFO] \node_modules\pomelo\lib\application.js - app.init invoked
[2013-03-23 11:47:46.792] [INFO] console - [2013-03-23 11:47:46.368] [INFO] \node_modules\pomelo\lib\application.js - app.init invoked
[2013-03-23 11:47:47.116] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] new register connection: "master-server-1", "master"
[2013-03-23 11:47:47.806] [INFO] console - [2013-03-23 11:47:46.482] [INFO] \node_modules\pomelo\lib\application.js - application inited: "gate-server-1" #初始化成功信息
[2013-03-23 11:47:47.829] [INFO] console - [2013-03-23 11:47:46.274] [INFO] \node_modules\pomelo\lib\application.js - application inited: "chat-server-2"
[2013-03-23 11:47:47.840] [INFO] console - [2013-03-23 11:47:46.225] [INFO] \node_modules\pomelo\lib\application.js - application inited: "chat-server-1"
[2013-03-23 11:47:47.840] [INFO] console - [2013-03-23 11:47:46.074] [INFO] \node_modules\pomelo\lib\application.js - application inited: "connector-server-3"
[2013-03-23 11:47:47.873] [INFO] console - [2013-03-23 11:47:45.678] [INFO] \node_modules\pomelo\lib\application.js - application inited: "connector-server-1"
[2013-03-23 11:47:47.875] [INFO] console - [2013-03-23 11:47:46.420] [INFO] \node_modules\pomelo\lib\application.js - application inited: "chat-server-3"
[2013-03-23 11:47:47.913] [INFO] console - [2013-03-23 11:47:45.994] [INFO] \node_modules\pomelo\lib\application.js - application inited: "connector-server-2"
[2013-03-23 11:47:47.914] [INFO] console - [2013-03-23 11:47:47.911] [INFO] console - info: 'socket.io started' #開始對剛初始化成功的服務器進行端口監聽
[2013-03-23 11:47:48.013] [INFO] console - [2013-03-23 11:47:47.832] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:48.035] [INFO] console - [2013-03-23 11:47:47.947] [INFO] \node_modules\pomelo\node_modules\pomelo-admin\lib\consoleService.js - try to connect master: "gate", "127.0.0.1", 3005 #monitor監聽端口
[2013-03-23 11:47:48.035] [INFO] console - [2013-03-23 11:47:47.826] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:48.043] [INFO] console - [2013-03-23 11:47:47.831] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:48.046] [INFO] console - [2013-03-23 11:47:47.958] [INFO] \node_modules\pomelo\node_modules\pomelo-admin\lib\consoleService.js - try to connect master: "chat", "127.0.0.1", 3005
[2013-03-23 11:47:48.049] [INFO] console - [2013-03-23 11:47:47.866] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:48.051] [INFO] console - [2013-03-23 11:47:47.962] [INFO] \node_modules\pomelo\node_modules\pomelo-admin\lib\consoleService.js - try to connect master: "connector", "127.0.0.1", 3005
[2013-03-23 11:47:48.060] [INFO] console - [2013-03-23 11:47:47.873] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:48.102] [INFO] console - [2013-03-23 11:47:48.031] [INFO] \node_modules\pomelo\node_modules\pomelo-admin\lib\consoleService.js - try to connect master: "connector", "127.0.0.1", 3005
[2013-03-23 11:47:48.156] [INFO] console - [2013-03-23 11:47:47.924] [INFO] \node_modules\pomelo\node_modules\pomelo-admin\lib\consoleService.js - try to connect master: "connector", "127.0.0.1", 3005
[2013-03-23 11:47:48.187] [INFO] console - [2013-03-23 11:47:47.957] [INFO] \node_modules\pomelo\node_modules\pomelo-admin\lib\consoleService.js - try to connect master: "chat", "127.0.0.1", 3005
[2013-03-23 11:47:48.195] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] new register connection: "chat-server-2", "chat"
[2013-03-23 11:47:48.200] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] new register connection: "gate-server-1", "gate"
[2013-03-23 11:47:48.202] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] new register connection: "connector-server-3", "connector"
[2013-03-23 11:47:48.231] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] new register connection: "chat-server-1", "chat"
[2013-03-23 11:47:48.239] [INFO] console - [2013-03-23 11:47:47.969] [INFO] \node_modules\pomelo\node_modules\pomelo-admin\lib\consoleService.js - try to connect master: "chat", "127.0.0.1", 3005
[2013-03-23 11:47:48.242] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] new register connection: "chat-server-3", "chat" #完成事件監聽註冊
[2013-03-23 11:47:48.259] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] new register connection: "connector-server-1", "connector"
[2013-03-23 11:47:48.292] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] new register connection: "connector-server-2", "connector"
[2013-03-23 11:47:48.293] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\master\master.js - [master] all servers have started and notify after start now...
[2013-03-23 11:47:48.295] [DEBUG] \chatofpomelo\game-server\node_modules\pomelo\lib\modules\afterStart.js - after start: "master-server-1"
[2013-03-23 11:47:48.295] [INFO] \chatofpomelo\game-server\node_modules\pomelo\lib\modules\afterStart.js - server "master-server-1" started.
[2013-03-23 11:47:48.296] [INFO] console - [2013-03-23 11:47:48.294] [DEBUG] \node_modules\pomelo\lib\modules\afterStart.js - after start: "chat-server-2"
[2013-03-23 11:47:48.295] [INFO] \node_modules\pomelo\lib\modules\afterStart.js - server "chat-server-2" started.
[2013-03-23 11:47:48.301] [INFO] console - [2013-03-23 11:47:48.297] [DEBUG] \node_modules\pomelo\lib\modules\afterStart.js - after start: "gate-server-1" #執行啓動完成後的操作
[2013-03-23 11:47:48.301] [INFO] console - [2013-03-23 11:47:48.296] [DEBUG] \node_modules\pomelo\lib\modules\afterStart.js - after start: "connector-server-3"
[2013-03-23 11:47:48.312] [INFO] console - [2013-03-23 11:47:48.295] [DEBUG] \node_modules\pomelo\lib\modules\afterStart.js - after start: "chat-server-1"
[2013-03-23 11:47:48.312] [INFO] console - [2013-03-23 11:47:48.297] [DEBUG] \node_modules\pomelo\lib\modules\afterStart.js - after start: "connector-server-2"
[2013-03-23 11:47:48.312] [INFO] console - [2013-03-23 11:47:48.304] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:48.314] [INFO] console - [2013-03-23 11:47:48.305] [DEBUG] \node_modules\pomelo\lib\modules\afterStart.js - after start: "connector-server-1"
[2013-03-23 11:47:48.314] [INFO] console - [2013-03-23 11:47:48.307] [DEBUG] \node_modules\pomelo\lib\modules\afterStart.js - after start: "chat-server-3"
[2013-03-23 11:47:48.315] [INFO] console - [2013-03-23 11:47:48.296] [INFO] \node_modules\pomelo\lib\modules\afterStart.js - server "chat-server-1" started.
[2013-03-23 11:47:48.315] [INFO] console - [2013-03-23 11:47:48.304] [INFO] \node_modules\pomelo\lib\modules\afterStart.js - server "connector-server-3" started.
[2013-03-23 11:47:48.315] [INFO] console - [2013-03-23 11:47:48.307] [INFO] \node_modules\pomelo\lib\modules\afterStart.js - server "chat-server-3" started.
[2013-03-23 11:47:48.316] [INFO] console - [2013-03-23 11:47:48.306] [INFO] console - info: 'socket.io started' #完成afterStart操作後,正式啓動完畢
[2013-03-23 11:47:48.306] [INFO] \node_modules\pomelo\lib\modules\afterStart.js - server "connector-server-2" started.
[2013-03-23 11:47:48.316] [INFO] console - [2013-03-23 11:47:48.313] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:48.316] [INFO] \node_modules\pomelo\lib\modules\afterStart.js - server "connector-server-1" started.
[2013-03-23 11:47:48.339] [INFO] console - [2013-03-23 11:47:48.338] [INFO] console - info: 'socket.io started'
[2013-03-23 11:47:48.339] [INFO] console - [2013-03-23 11:47:48.339] [INFO] \node_modules\pomelo\lib\modules\afterStart.js - server "gate-server-1" started.