pomelo源代碼分析(一)

        千里之行始於足下,一直說想了解pomelo,對pomelo有興趣,但一直遲遲沒有去碰,儘管對pomelo進行源代碼分析,在網絡上確定不止我一個,已經有很是優秀的前輩走在前面,如http://golanger.cn/,在閱讀Pomelo代碼的時候,已經連載到了11篇了,在個人源代碼分析參考了該博客,固然,也會添�我對pomelo的理解,藉此但願能提升一下本身對node.js的瞭解和學習一些優秀的設計。javascript

  • 開發環境:win7
  • 調試環境:webstorm5.0
  • node.js版本號:v0.8.21
  • 源代碼版本號package.json:

{
	"name": "chatofpomelo",
	"version": "0.0.1",
	"private": false,
	"dependencies": {
		"pomelo": "0.2.0",
		"log4js": ">= 0.4.1",
		"crc": ">=0.0.1"
	}
}

gameserver/app.jsjava

var pomelo = require('pomelo');
var routeUtil = require('./app/util/routeUtil');
/**
 * Init app for client.
 */
var app = pomelo.createApp();     //建立Application
app.set('name', 'chatofpomelo');  //設置Application名字


// app configure  
app.configure('production|development', function() {  
	// route configures
	app.route('chat', routeUtil.chat);

	// filter configures
	app.filter(pomelo.timeout());
});

// start app
app.start();

process.on('uncaughtException', function(err) {
	console.error(' Caught exception: ' + err.stack);
});

注意:在webstorm下調試,可能因爲工做文件夾的設置緣由會致使應用的運行路徑問題,致使沒法讀取配置文件,因此需要依據實際狀況改動例如如下

var opt = {'base':'D:\\src\\pomelo\\chatofpomelo\\game-server'}
var app = pomelo.createApp(opt);
app.set('name', 'chatofpomelo');

opt.base 是你的game-server的實際文件夾路徑,詳細可以依據本身需要來定製

app.js 是game-server的主要入口,主要負責建立application,讀取配置文件,應用到application設置上,並利用app.start()來運行實際的master,monitor等服務器的start,對於聊天室程序來講,還要作簡單的路由和過濾設置。node


application, 應用的定義、component管理,上下文配置, 這些使pomelo framework的對外接口很是easy, 並且具備鬆耦合、可插拔架構。
golang

所有server的啓動都是從執行app.js開始。每一個server的啓動都首先建立一個全局惟一的application對象,該對象中掛載了所在server的所有信息,包含server物理信息、server邏輯信息、以及pomelo的組件信息等。同一時候,該對象還提供應用管理和配置等基本方法。 在app.js中調用app.start()方法後,application對象首先會經過loadDefaultComponents方法載入默認的組件。web


pomelo/lib/pomelo.js
json

var application = require('./application');

Pomelo.createApp = function (opts) {
  var app = application;
  app.init(opts);
  self.app = app;
  return app;
};

pomelo/lib/application.js

/**
 * Application prototype.
 *
 * @module
 */
var Application = module.exports = {};

/**
 * Application states
 */
var STATE_INITED  = 1;  // app has inited
var STATE_START = 2;  // app start
var STATE_STARTED = 3;  // app has started
var STATE_STOPED  = 4;  // app has stoped

/**
 * Initialize the server.
 *
 *   - setup default configuration
 *
 * @api private
 */
Application.init = function(opts) {
  opts = opts || {};
  logger.info('app.init invoked');
  this.loaded = [];
  this.components = {};
  this.settings = {};   // set,和get功能的容器
  this.set('base', opts.base);  //設置服務器的工做文件夾
  this.defaultConfiguration();  //依據配置文件,載入master,monitor等服務器
  this.state = STATE_INITED;  //application工做狀態
  logger.info('application inited: %j', this.get('serverId'));
};

pomelo/lib/application.js

/**
 * Initialize application configuration.
 *
 * @api private
 */
Application.defaultConfiguration = function () {
  var args = utils.argsInfo(process.argv);
  this.setupEnv(args); //application環境設置
  this.loadServers();  //載入server配置信息
  this.loadConfig('master', this.getBase() + '/config/master.json'); //載入materserver配置信息
  this.processArgs(args); //依據啓動參數設定server配置
  this.configLogger();
};

utils.argsInfo(process.argv); 獲取系統啓動參數,咱們最好仍是看看究竟有哪些參數支持 

啓動game-server服務器:>pomelo start [development | production] [--daemon]
api


依據args參數設定application的工做環境是development或production服務器

/**
 * Setup enviroment.
 * @api private
 */
Application.setupEnv = function(args) {
  this.set('env', args.env || process.env.NODE_ENV || 'development', true);
};

載入服務器信息,並且保存在__serverMap___內存下

/**
 * Load server info from configure file.
 *
 * @api private
 */
Application.loadServers = function() {
  this.loadConfig('servers', this.getBase() + '/config/servers.json');
  var servers = this.get('servers');
  var serverMap = {}, slist, i, l, server;
  for(var serverType in servers) {
    slist = servers[serverType];
    for(i=0, l=slist.length; i<l; i++) {
      server = slist[i];
      server.serverType = serverType;
      serverMap[server.id] = server;
    }
  }

  this.set('__serverMap__', serverMap);
};

server.json

{
    "development":{
        "connector":[
             {"id":"connector-server-1", "host":"127.0.0.1", "port":4050, "wsPort":3050},
             {"id":"connector-server-2", "host":"127.0.0.1", "port":4051, "wsPort":3051},
             {"id":"connector-server-3", "host":"127.0.0.1", "port":4052, "wsPort":3052}
         ],
        "chat":[
             {"id":"chat-server-1", "host":"127.0.0.1", "port":6050},
             {"id":"chat-server-2", "host":"127.0.0.1", "port":6051},
             {"id":"chat-server-3", "host":"127.0.0.1", "port":6052}
        ],
        "gate":[
	     {"id": "gate-server-1", "host": "127.0.0.1", "wsPort": 3014}
	]
    },
    "production":{
       "connector":[
             {"id":"connector-server-1", "host":"127.0.0.1", "port":4050, "wsPort":3050},
             {"id":"connector-server-2", "host":"127.0.0.1", "port":4051, "wsPort":3051},
             {"id":"connector-server-3", "host":"127.0.0.1", "port":4052, "wsPort":3052}
         ],
        "chat":[
             {"id":"chat-server-1", "host":"127.0.0.1", "port":6050},
             {"id":"chat-server-2", "host":"127.0.0.1", "port":6051},
             {"id":"chat-server-3", "host":"127.0.0.1", "port":6052}
        ],
        "gate":[
	     {"id": "gate-server-1", "host": "127.0.0.1", "wsPort": 3014}
	]
  }
}

工具函數,讀取json配置文件,在這裏讀取的是master.json文件網絡

/**
 * Load Configure json file to settings.
 *
 * @param {String} key environment key
 * @param {String} val environment value
 * @return {Server|Mixed} for chaining, or the setting value
 *
 * @memberOf Application
 */
Application.loadConfig = function (key, val) {
  var env = this.get('env');
  val = require(val);
  if (val[env]) {
    val = val[env];
  }
  this.set(key, val);
};


master.json
{
    "development":{
        "id":"master-server-1",
        "host":"127.0.0.1",
        "port":3005,
        "queryPort":3015,
        "wsPort":2337
    },

    "production":{
        "id":"master-server-1",
        "host":"127.0.0.1",
        "port":3005,
        "queryPort":3015,
        "wsPort":2337
    }

}

依據進程讀取配置好的參數,配置server。

Application.processArgs = function(args){
  var serverType = args.serverType || 'master';
  var serverId = args.serverId || this.get('master').id;
  this.set('main', args.main, true);
  this.set('serverType', serverType, true);
  this.set('serverId', serverId, true);
  if(serverType !== 'master') {
    this.set('curServer', this.getServerById(serverId), true);
  } else {
    this.set('curServer', this.get('master'), true);
  }
};

項目的日誌配置

Application.configLogger = function() {
  if(process.env.POMELO_LOGGER !== 'off') {
    log.configure(this, this.getBase() + '/config/log4js.json');
  }
};

log4js.json

{
  "appenders": [
    {
      "type": "file",
      "filename": "./logs/node-log-${opts:serverId}.log",
      "fileSize": 1048576,
      "layout": {
        "type": "basic"
      }, 
      "backups": 5
    },
    {
      "type": "console"
    },
    {
      "type": "file",
      "filename": "./logs/con-log-${opts:serverId}.log", 
      "pattern": "connector", 
      "fileSize": 1048576,
      "layout": {
          "type": "basic"
        }
      ,"backups": 5,
      "category":"con-log"
    },
    {
      "type": "file",
      "filename": "./logs/rpc-log-${opts:serverId}.log",
      "fileSize": 1048576,
      "layout": {
          "type": "basic"
        }
      ,"backups": 5,
      "category":"rpc-log"
    },
    {
      "type": "file",
      "filename": "./logs/forward-log-${opts:serverId}.log",
      "fileSize": 1048576,
      "layout": {
          "type": "basic"
        }
      ,"backups": 5,
      "category":"forward-log"
    },
    {
      "type": "file",
      "filename": "./logs/crash.log",
      "fileSize": 1048576,
      "layout": {
          "type": "basic"
        }
      ,"backups": 5,
      "category":"crash-log"
    }
  ],

  "levels": {
  	"rpc-log" : "ERROR", 
    "forward-log": "ERROR"
  }, 

  "replaceConsole": true
}
相關文章
相關標籤/搜索