pomelo是网易推出的开源游戏服务端框架,采用Node.js编写。最近在学习的时候感觉官方文档对框架的描述抽象层次太高,在这里把深入学习的过程记录下来。
先来了解一下pomelo的”分布式”,以 https://github.com/NetEase/chatofpomelo 这个demo为例
game-server/config/servers.json 是核心配置文件:
"development":{ "connector":[ {"id":"connector-server-1", "host":"127.0.0.1", "port":4050, "clientPort": 3050, "frontend": true}, {"id":"connector-server-2", "host":"127.0.0.1", "port":4051, "clientPort": 3051, "frontend": true}, {"id":"connector-server-3", "host":"127.0.0.1", "port":4052, "clientPort": 3052, "frontend": true} ], "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", "clientPort": 3014, "frontend": true} ] },
[INFO] /node_modules/pomelo/lib/application.js - application inited: "master-server-1"
服务(server)是pomelo实现“分布式”的方式,每个server对应一个进程,这个是很重要的概念。
master会根据servers.json 里的配置,将server对应的进程启动。
对于上面配置里第一个server,用如下方式启动:
cd /Users/wangdy/Projects/pomelo/chatofpomelo-master/game-server && node /Users/wangdy/Projects/pomelo/chatofpomelo-master/game-server/app.js env=development id=connector-server-1 host=127.0.0.1 port=4050 clientPort=3050 frontend=true serverType=connector locally
可以看到servers.json里的配置其实都是启动进程的参数。每个server有id,host,port,serverType等属性。id是全局唯一的,多个serverType相同的server可以构成一组。
整个系统用的同一个配置文件,如何实现分布式呢?
pomelo的分布式可以称作“多进程分布式”,在 lib/master/starter.js 可以看到,进程启动的方式有两种,sshrun和localrun。
pomelo的做法是:在所有主机里部署目录结构相同的程序,非master主机与master主机配置好ssh agent forward。master程序启动的时候,判断host属性,如果host是本地,通过localrun直接启动,如果host不是本地主机,则通过ssh远程登录启动。
Server进程启动后,创建并维护着application的实例app, app除了提供一些基本的配置和驱动接口,更多的是充当着服务进程上下文的角色。app里通过组件(component)实现各种功能。
组件对象存放在app对象的 components 属性里,在lib/util/appUtil.js的loadDefaultComponents方法里,可以看到app默认加载的组件,包括: connnection,connector,session,localSession,channel,server,monitor等。其中server组件完成最核心的客户请求处理功能。
server组件(lib/components/server.js)只是简单的实现了组件的start,stop接口,具体功能由属性server对象实现(lib/server/server.js)。
Server对象的构造函数:
var Server = function (app) {
this.app = app;
this.filterService = null;
this.handlerService = null;
this.state = ST_INITED;
};
其中handlerService属性存放的是HandlerService对象(lib/common/service/handleService.js),此对象加载并管理我们编写的处理客户端请求的 xxxHandle.js ,filterService则是通过FilterService管理filter对象。
未完待续。。。