千里之行始于足下,一直说想了解pomelo,对pomelo有兴趣,但一直迟迟没有去碰,尽管对pomelo进行源代码分析,在网络上肯定不止我一个,已经有非常优秀的前辈走在前面,如http://golanger.cn/,在阅读Pomelo代码的时候,已经连载到了11篇了,在我的源代码分析參考了该博客,当然,也会添�我对pomelo的理解,借此希望能提高一下自己对node.js的了解和学习一些优秀的设计。

  • 开发环境: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.js

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,对于聊天室程序来说,还要做简单的路由和过滤设置。

application, 应用的定义、component管理,上下文配置, 这些使pomelo framework的对外接口非常easy, 而且具有松耦合、可插拔架构。

全部server的启动都是从执行app.js開始。每个server的启动都首先创建一个全局唯一的application对象,该对象中挂载了所在server的全部信息,包含server物理信息、server逻辑信息、以及pomelo的组件信息等。同一时候,该对象还提供应用管理和配置等基本方法。 在app.js中调用app.start()方法后,application对象首先会通过loadDefaultComponents方法载入默认的组件。



pomelo/lib/pomelo.js

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]



依据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
}

pomelo源代码分析(一)的更多相关文章

  1. android-plugmgr源代码分析

    android-plugmgr是一个Android插件加载框架,它最大的特点就是对插件不需要进行任何约束.关于这个类库的介绍见作者博客,市面上也有一些插件加载框架,但是感觉没有这个好.在这篇文章中,我 ...

  2. Twitter Storm源代码分析之ZooKeeper中的目录结构

    徐明明博客:Twitter Storm源代码分析之ZooKeeper中的目录结构 我们知道Twitter Storm的所有的状态信息都是保存在Zookeeper里面,nimbus通过在zookeepe ...

  3. 转:SDL2源代码分析

    1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...

  4. 转:RTMPDump源代码分析

    0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...

  5. 转:ffdshow 源代码分析

    ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...

  6. UiAutomator源代码分析之UiAutomatorBridge框架

    上一篇文章<UIAutomator源代码分析之启动和执行>我们描写叙述了uitautomator从命令行执行到载入測试用例执行測试的整个流程.过程中我们也描写叙述了UiAutomatorB ...

  7. MyBatis架构设计及源代码分析系列(一):MyBatis架构

    如果不太熟悉MyBatis使用的请先参见MyBatis官方文档,这对理解其架构设计和源码分析有很大好处. 一.概述 MyBatis并不是一个完整的ORM框架,其官方首页是这么介绍自己 The MyBa ...

  8. hostapd源代码分析(三):管理帧的收发和处理

    hostapd源代码分析(三):管理帧的收发和处理 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004379 这篇文章我来讲解一下h ...

  9. hostapd源代码分析(二):hostapd的工作机制

    [转]hostapd源代码分析(二):hostapd的工作机制 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004433 在我的上一 ...

随机推荐

  1. Bootstrap &quot;row&quot;类宽度超过问题

    问题原因: VOORBootstrap门格系统布局,类别col-xs-*身边有15px的padding,在这样的元素img我们希望展现的顶部边缘,这需要col-xs-*式:padding:0px; 如 ...

  2. 双击GridView查看详情

    效果如下: protected void gvEquData_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowTy ...

  3. 利用FFT 计算生成离散解析信号

    通常我们用到的信号都是实值信号,但是我们可以根据这个实信号构造出一个复信号,使得这个复信号只包含正频率部分,而且这个复信号的实部正好就是我们原来的实值信号.简单的推导可知,复信号的虚部是原信号的希尔伯 ...

  4. android 播放音乐-进度条

    今天学渣研究了一下使用MediaPlayer播放音乐时加入进度条,进度条如今用的是android自带的seekbar,后期会跟换UI的,在之前可以播放音乐的基础上,如今加入的主要功能有两个: 1实时显 ...

  5. 操作系统的页面置换C++算法:OPT FIFO LRU CLOCK 计算缺页率

    暴力直接上代码,主要是用了vector来实现,有些方法比較费时,不太好,请各位大神斧正.这是个人的作业,  这是代码下载页http://download.csdn.net/detail/l631068 ...

  6. Android应用公布的准备——渠道注冊与认证

    今天早上申请了一个早上的渠道账号,这工作真是太繁琐,申请的是企业账号,须要营业执照等相关资料,假设申请个人的话预计须要身份证相关信息.以下贴出国内主流的几个渠道.不全然,可是基本上涵盖了大部分. 36 ...

  7. android 定时拍照并发送微博

    最近在做android方面的开发,下面是android自动对焦并拍照的小例子: package com.comnvi.camera; import java.io.File; import java. ...

  8. 开源数据库连接池之DBCP

    本篇介绍几种开源数据库连接池,同时重点讲述如何使用Apache公司的的DBCP数据库连接池. 前面一篇博客已经重点讲述了使用数据库连接池的好处,即是将多次创建连接转变为一次创建而使用长连接模式.这样能 ...

  9. linux命令:使用man, 导出man

    要查一个命令怎么使用,使用"man 命令", eg: man find, man ls; "info 命令"貌似也可以看, info find, info ls ...

  10. QSettings操作配置文件

    用Qt写界面时,难免会进行本地信息的保存,可以使用轻量级数据库sqlite,也可以使用QSettings读写配置文件.     如何来进行读写呢?如下,使用QSettings写一个通用的读写方法:   ...