技术文章 > 服务端 > pomelo 架构概览 

pomelo 架构概览

pomelo 之所以简单易用、功能全面,并且具有高可扩展性、可伸缩性等特点,这与它的技术选型和方案设计是密不可分的。在研究大量游戏引擎设计思路基础上,结合以往游戏开发的经验,确定了pomelo框架的设计方案。

1、pomelo为什么采用 node.js 开发


node.js 自身特点与游戏服务器的特性惊人的吻合。 在 node.js 的官方定义中, fast、scalable、realtime、network 这几个特性都非常符合游戏服务器的要求。游戏服务器是个网络密集型的应用,对实时性要求极高,而 node.js 在网络 io 上的优势也完全可以满足这点。使用 node.js 开发游戏服务器的优势总结:

2、游戏服务器的运行架构


一个真正高可扩展的游戏运行架构必须是多进程的。google 的 gritsgame, mozilla 的 browserquest 都采用了 node.js 作为游戏服务器开发语言, 但它们都采用了单进程的 node.js 服务器,缺乏扩展性,这使它们可以支撑的在线用户数量是很有限的(这两个游戏主要是作为 HTML5 游戏的 demo )。而多进程的架构可以很好的实现游戏服务器的的扩展性,达到支撑较多在线用户、降低服务器压力等要求。
一个典型的多进程 MMO 运行架构, 如下图所示:



说明: 上图中的方块表示进程, 定义上等同于“服务器”

运行架构说明:

游戏运行架构与 web 应用运行架构的区别:

该游戏运行架构表面上看与 web 应用运行架构很类似,connector 类似于 web 应用的 apache/nginx 等 web 服务器,后端的服务器群类似于 web 应用中的应用服务器(如 tomcat ),但实际上存在着很大的差别:

复杂的运行架构需要一个框架来简化开发

游戏的运行架构很复杂,要想支撑起如此复杂的运行架构,必须要有一个框架来简化开发。 pomelo 正是这样一个框架,它使我们用最少的代码, 最清晰的结构来实现复杂的运行架构。

3、pomelo 的框架介绍

pomelo framework 的组成架构如图所示:



3.1、pomelo 的架构设计目标

3.2、服务器(进程)的抽象与扩展介绍

服务器的抽象与分类
该架构把游戏服务器做了抽象, 抽象成为两类:前端服务器和后端服务器, 如图:


前端服务器 (frontend) 的职责: 后端服务器 (backend) 的职责:
服务器的鸭子类型
动态语言的面向对象有个基本概念叫鸭子类型。 服务器的抽象也同样可以比喻为鸭子, 服务器的对外接口只有两类, 一类是接收客户端的请求, 叫做 handler, 一类是接收 RPC 请求, 叫做 remote, handler 和 remote 的行为决定了服务器长什么样子。 因此我们只要定义好 handler 和 remote 两类的行为, 就可以确定这个服务器的类型。
服务器抽象的实现
利用目录结构与服务器对应的形式, 可以快速实现服务器的抽象。以下是示例图:



图中的 connector, area, chat 三个目录代表三类服务器类型, 每个目录下的 handler 与 remote 决定了这个服务器的行为(对外接口)。 开发者只要往 handler 与 remote 目录填代码, 就可以实现某一类的服务器。这让服务器实现起来非常方便。 让服务器动起来, 只要填一份配置文件 servers.json 就可以让服务器快速动起来。 配置文件内容如下所示:
{
  "development":{
	"connector": [
	  {"id": "connector-server-1", "host": "127.0.0.1", "port": 3150, "clientPort":3010, "frontend":true},
	  {"id": "connector-server-2", "host": "127.0.0.1", "port": 3151, "clientPort":3011, "frontend":true}
	],
	"area": [
	  {"id": "area-server-1", "host": "127.0.0.1", "port": 3250, "area": 1},
	  {"id": "area-server-2", "host": "127.0.0.1", "port": 3251, "area": 2},
	  {"id": "area-server-3", "host": "127.0.0.1", "port": 3252, "area": 3}
	],
	"chat":[
	  {"id":"chat-server-1","host":"127.0.0.1","port":3450}
	]
   }
}

3.3、客户端请求与响应、广播的抽象介绍

所有的 web 应用框架都实现了请求与响应的抽象。尽管游戏应用是基于长连接的, 但请求与响应的抽象跟 web 应用很类似。 下图的代码是一个 request 请求示例:



上图的 remote 目录里定义了一个 RPC 接口:chatRemote.js,它的接口定义如下:
chatRemote.kick = function(uid, player, cb) {
}
其它服务器(RPC 客户端)只要通过以下接口就可以实现 RPC 调用:
app.rpc.chat.chatRemote.kick(session, uid, player, function(data){
});
这个调用会根据特定的路由规则转发到特定的服务器。(如场景服务的请求会根据玩家在哪个场景直接转发到对应的 server )。 RPC 框架目前在底层采用 socket.io 作为通讯协议,但协议对上层是透明的,以后可以替换成任意的协议。

3.4、pomelo 支持可插拔的 component 扩展架构

component 是 pomelo 自定义组件,开发者可自加载自定义的 component。 component 在 pomelo 框架参考将有更深入的讨论。 以下是 component 的生命周期图:



用户只要实现component相关的接口: start, afterStart, stop, 就可以加载自定义的组件:
app.load([name], comp, [opts])

总结

上面的应用框架构成了 pomelo framework 的基础。在此基础上,配合 pomelo 提供的游戏开发库和相关工具集,开发游戏服务器将变得非常方便。


来源:摘自 https://github.com/NetEase/pomelo/wiki/pomelo%E6%9E%B6%E6%9E%84%E6%A6%82%E8%A7%88https://github.com/node-pinus/pinus/wiki/pinus%E6%9E%B6%E6%9E%84%E6%A6%82%E8%A7%88,本站 行痴 整理,2023-08-21