Pomelo MMORPG
环境准备
$ mkdir mmorpg && cd rpg
$ pomelo ini
$ npm-install.bat
服务器类型
游戏采用分布式设计,服务端是由一个服务器集群所组成。
序号 | 服务器类型 | 名称 | 数量 |
---|---|---|---|
1 | 网关服务器 | gate | 1 |
2 | 连接服务器 | connector | 1 |
3 | 聊天服务器 | chat | 1 |
4 | 认证服务器 | auth | 1 |
5 | 场景服务器 | area | n |
6 | 寻路服务器 | path | 1 |
7 | 管理服务器 | manager | 1 |
网关服务器gate
- 网关服务器为用户提供统一的
websocket
入口 - 网关服务器会向所有客户端暴露一个固定的
websocket
接口 - 网关服务器负责用户验证和连接服务器的分配
- 网关服务器一般只有一台
当用户登录时会首先连接网关服务器完成验证并获得由网关服务器分配的对应连接服务器的地址,之后客户端会断开与网关服务器的连接,通过获取的地址连接对应的连接服务器以获取对应的服务。
连接服务器 connector
与web短连接模式不同的是,网络游戏中客户端和服务器建立的都是长连接,长连接本身需要一定的资源来维持。
本游戏中使用websocket协议在客户端和服务器之间建立连接,连接服务器是用来维护这些连接,并中转客户端和服务器之间的消息。
本游戏中客户端和服务器的连接是通过一个抽象的会话来维护的,会话是一个客户端在服务端的标识,用来维护用户的登录状态、用户的基本信息、用户的websocket连接信息等。
认证服务器auth
- 认证服务器负责用户注册和验证,作为用户验证的统一入口。
- 认证服务器提供远程调用接口供其它服务器调用来进行用户身份验证
- 认证服务器的主要作用是屏蔽认证验证的细节为其它服务器提供统一的验证接口
聊天服务器 chat
- 聊天服务器是网游的基本服务之一,通过独立的服务器实现。
- 聊天服务器维护一份所有在线用户的数据,通过这些数据与连接服务器通讯,实现用户之间的即时通讯。
场景服务器 area
- 网游中处于性能和负载考量,大的游戏世界会被划分为多个区域即场景。
- 本游戏中一张地图即一个游戏场景与一台独立的场景服务器对应
- 场景是构成游戏世界的基本单位,不能进行分隔和合并扩展。
- 场景服务器负责维护场景中所有实体并驱动实体AI运行游戏逻辑
- 场景服务器负责处理游戏中几乎所有的逻辑同时为其它服务器提供操纵场景数据的接口
- 虽然场景本身不可分隔但可通过加入新的场景的方式来分散用户从而提高游戏服务器总体负载
- 一些与场景相关的服务通过独立运行的方式进行水平扩展
寻路服务器path
- 寻路服务器是游戏服务器基本服务之一
- 玩家跑动、怪物移动都需要寻路服务器提供支持
- 寻路服务器是根据地图的起点和重点得到两点之间的最优路径
- 由于寻路是典型的无状态、计算密集型服务,因此将寻路与场景逻辑分离,放在单独的服务器中。从而减轻场景服务器的压力。
- 寻路服务器可根据简单并行进行扩展
- 寻路算法使用AI实现并提供通用的计算接口,并封装为一个模块。
管理服务器manager
管理服务器是后端服务器集群中负责全局管理副本全生命周期和组队相关操作的功能服务器。
组队功能模块team
组队功能是玩家之间互动的一种方式,玩家可创建队伍并邀请其它玩家加入,其它玩家也可以主动向队长踢出申请加入队伍,队伍的人数上限为3。
teamHandler.js
为协议入口模块,负责负责队伍相关操作的前期判断和后期通知。teamHandler
完成前期判断后通过一个rpc将操作所需的参数传递给manager服务器。队伍对象的管理工作是由manager服务器所持有一个全局的teamManager.js
模块负责的,teamManager
中管理所有的team对象的创建、更改、销毁等操作。
队伍id从1开始递增,所有场景中的队伍使用统一的id序列,当manager服务器重启时,队伍id也重新初始化为1.
team.js
模块中维护一个队伍对象中的所有成员与成员身份,维护一个队伍频道来通知各个成员队伍相关的消息及进行队伍内的聊天。
同一个队伍中的玩家可以进入同一个组队副本。
副本功能模块instance
副本instance.js
本质上是一个临时的场景,并对进入该临时场景的玩家进行限制。instance由模块instancePool.js
来统一管理,这与队伍模块的结构是相同的。
目前有两种副本可供玩家进入分别是单人副本、组队副本。当队伍中有两个以上玩家时,队长点击进入组队副本时,队伍中的队员会同时拉入副本中,队伍中的队员也可以单独进入组队副本,但不会触发将队伍中的其它成员拉入副本的操作,其它成员可以分别进入该副本。
玩家进入副本也被视为场景切换,在areaService.js
模块中changeArea函数中进行目标场景类型判断,如果是普通场景则正常切换。如果是副本场景则通过一个rpc来创建副本。组队副本创建时的id与队伍id相关。单人副本创建时的id与玩家id相关。组队副本创建成功后,如果是队长触发的操作则向其它队员客户都拿发送进入副本的命令,如果是队员则直接进入副本中。
服务器配置
配置游戏服务器类型
$ vim game-server/config/adminServer.json
[{"type": "gate","token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"},{"type": "connector","token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"},{"type": "chat","token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"},{"type": "auth","token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"},{"type": "area","token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"},{"type": "path","token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"},{"type": "manager","token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"}
]
配置不同类型服务器的参数
$ vim game-server/config/servers.json
{"development":{"gate": [{"id": "gate-server-1","host": "127.0.0.1","clientPort": 3014,"frontend": true}],"connector": [{"id": "connector-server-1","host": "127.0.0.1","port": 3150,"clientHost": "127.0.0.1","clientPort": 3010,"frontend": true},{"id": "connector-server-2","host": "127.0.0.1","port": 3151,"clientHost": "127.0.0.1","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},{"id": "instance-server-1","host": "127.0.0.1","port": 3260,"instance": true},{"id": "instance-server-2","host": "127.0.0.1","port": 3261,"instance": true},{"id": "instance-server-3","host": "127.0.0.1","port": 3262,"instance": true}],"chat": [{"id": "chat-server-1","host": "127.0.0.1","port": 3450}],"path": [{"id": "path-server-1","host": "127.0.0.1","port": 3550}],"auth": [{"id": "auth-server-1","host": "127.0.0.1","port": 3650}],"manager": [{"id": "manager-server-1","host": "127.0.0.1","port": 3750}]},"production":{}
}
序号 | 服务器类型 | 名称 | 数量 | rpc ip | rpc port | client ip | client port |
---|---|---|---|---|---|---|---|
1 | 网关服务器 | gate | 1 | - | - | 127.0.0.1 | 3014 |
2 | 连接服务器 | connector | 2 | 127.0.0.1 | 315x | 127.0.0.1 | 301x |
3 | 场景服务器 | area | 6 | 127.0.0.1 | 325x | - | - |
4 | 聊天服务器 | chat | 1 | 127.0.0.1 | 3450 | - | - |
5 | 寻路服务器 | path | 1 | 127.0.0.1 | 3550 | - | - |
6 | 认证服务器 | auth | 1 | 127.0.0.1 | 3650 | - | - |
7 | 管理服务器 | manager | 1 | 127.0.0.1 | 3750 | - | - |
其中场景服务器又分为两种类型分别是普通的场景服务器和副本服务器
序号 | 服务器类型 | 服务器名称 | 是否副本 |
---|---|---|---|
1 | 场景服务器 | area-server-1 | 否 |
2 | 场景服务器 | area-server-2 | 否 |
3 | 场景服务器 | area-server-3 | 否 |
4 | 副本服务器 | instance-server-1 | 是 |
5 | 副本服务器 | instance-server-2 | 是 |
6 | 副本服务器 | instance-server-3 | 是 |
启动流程
app.js是游戏服务器的入口,主要负责所有服务器的配置,以及组件的加载和启动。本项目的启动主要分为两步:先启动pomelo的master服务器,再由pomelo的master服务器分别启动其它服务器。
项目启动采用pomelo的启动方式,即将master作为默认组件,在app.js中调用app.start()方法后加载并启动master服务。master组件会负责启动其它服务,启动过程分为两个阶段:
- 第一阶段
master服务启动其它所有服务,在服务器启动完毕后,其中monitor组件会连接到master对应的监听端口上,表明该服务器启动完毕。 - 第二阶段
当所有服务器启动完毕后,master会调用所有服务器上的afterStart接口来执行后续处理流程。
组件的加载和配置
本项目使用多个外部组件,这些组件在服务器启动时加载以提供各种服务,诸如数据统计、路由替换、游戏场景初始化等。
自定义在线统计模块
项目中使用了基于脚本的统计,组件通过运行自定义的脚本,收集服务器运行数据并生成报告。
$ vim game-server/modules/online.js
//自定义监控模块
let Module = function(opts){console.log("online modules constructor");opts = opts||{};//当前监控模块所监测的服务器实例this.app = opts.app;//获取数据的方式// pomelo-admin提供两种方式一种是pull拉取,一种是push推送// pull拉取表示master服务器会主动从各个游戏服务器上拉取所需的监控数据// push推送表示游戏服务器向master服务器推送监控数据this.type = opts.type || "pull";//每次push或pull的时间间隔this.interval = opts.interval || 5;
};// 监控模块标识
// 用于唯一标识监控模块,非常重要。
// 如果要向该模块获取和发送数据都需要依靠这个ID作为参数
// 如果需要让外部程序获取该模块的监控数据也必须依靠此参数
Module.moduleId = "online";// 采用pull拉取 当接收到master主服务器拉通知时回调
// 采用push推送 每次到达interval间隔时间时回调
Module.prototype.monitorHandler = function(agent, msg){console.log("online modules handler");//获取连接组件服务const connectionService = this.app.components.__connection__;if(!connectionService){console.log("not support connection: %j", agent.id);return;}//代理通知连接统计信息const info = connectionService.getStatisticsInfo();//通知admin的消息给master服务器agent.notify(Module.moduleId, info);
};// 采用pull拉取 每次到达pull拉取时间间隔时会被调用
// 采用push推送 当接收到游戏服务器push推送数据回调
Module.prototype.masterHandler = function(agent, msg){console.log("online master handler", msg, Module.moduleId);//若无消息则通知所有的monitor监视器去获取数据if(!msg){//通知指定类型的监听器获取获取数据const type = "connector";const list = agent.typeMap[type];if(!list || list.length===0){agent.notifyByType(type, Module.moduleId);}else{//通知所有监视器去获取数据agent.notifyAll(Module.moduleId);}return;}//从monitor监视器中收集数据let data = agent.get(Module.moduleId);if(!data){data = {};agent.set(Module.moduleId, data);}data[msg.serverId] = msg;
};//当第三方程序调用时 获取监控数据接口时回调
Module.prototype.clientHandler = function(agent, msg, cb){console.log("online client handler");if(!!cb && typeof cb==="function"){const param = agent.get(Module.moduleId) || {};//处理客户端请求直接返回数据并缓存到master服务器cb(null, param);}
};//导出模块
module.exports.moduleId = Module.moduleId;
module.exports = function(opts){return new Module(opts);
};
启动脚本中为所有服务器添加在线统计,也可以单独为connector连接服务器添加。
$ game-server/app.js
//应用全局配置 针对所有服务器
app.configure("production|development", function(){//开启系统监控 Linux环境有效app.enable("systemMonitor");//配置自定义监控:运行自定义统计脚本收集服务器运行数据,为服务器注册自定义监控模块。if(typeof app.registerAdmin === "function"){//将监控在线用户模块注册给所有服务器app.registerAdmin("online", require("./app/modules/online"), {app:app});}
});
Pomelo MMORPG相关推荐
- MMORPG传奇类手游《空空西游》完整源码(客户端cocos2d-js+服务端pomelo+cocosStudio工程+搭建教程)
MMORPG传奇类手游<空空西游>完整源码,包括:客户端cocos2d-js+服务端pomelo+cocosStudio工程+搭建教程. 客户端:cocos2d-js 服务端:pomelo ...
- pomelo服务器 性能,Pomelo游戏服务器端开发系列(1)-介绍
Pomelo框架总结 A fast,scalable,distributed game server framework for Node.js 联系我 Pomelo交流群 @老顽童-NextZeus ...
- Pomelo框架总结
Pomelo框架总结 A fast,scalable,distributed game server framework for Node.js 联系我 Pomelo交流群 @老顽童-NextZeus ...
- windows下pomelo开发环境搭建及JS乱码问题
from: http://blog.csdn.net/wangqiuyun/article/details/9243263 最近一直在研究node.js这一块,为的就是使用网易的pomelo框架,学习 ...
- 使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?(非常稳定、捕获所有异常、非常适合从头开始,但大公司已经有现成的C++框架、所以不会使用)
使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?(非常稳定.捕获所有异常.非常适合从头开始,但大公司已经有现成的C++框架.所以不会使用) 参考文章: (1)使用 Go 语言开发大型 MMO ...
- CocosCreator游戏开发---菜鸟学习之路(三)如何在CocosCreator中使用Pomelo
PS(废话): 这段时间都在研究网易的Pomelo框架,作为新手小白,自然遇到了不少坑爹的事情.(当然也有可能是因为自己技术不过关的原因所以导致在很多基础的问题上纠结了很久.)网上也搜索了好久,但是基 ...
- pomelo php,Nginx 502 Bad Gateway 自动重启shell脚本
星期三, 2013-08-14 | Author: LeeAuthor: Lee Name: lee Email: service@i5a6.com Site: https://www.pomelol ...
- 【1】万魂杀MMORPG研发回顾
为什么80%的码农都做不了架构师?>>> 万魂杀项目历时将近2年.在这期间,整个研发组都经历了较大的心里压力和工作压力.谨以该系列博文献给曾经一起奋斗的兄弟. 后续博文将按照服 ...
- pomelo 分布式聊天入门客户端demo(c#)
2019独角兽企业重金招聘Python工程师标准>>> ## c/s 聊天例子 目的:实现了一个简单的c/s分布式聊天例子,演示了c#客户端和pomelo服务器的交互,使用原生soc ...
- 从数值、玩法、社交模块入手谈MMORPG手游设计
剑灵手游在韩服首发已有一年半,上个月登录台服,稍稍体验了一下.本文接下来将轻度漫谈一下--韩国与国内MMO手游设计,包含的范围主要为数值->玩法->社交三点. 我们先对三个模块进行简单的定 ...
最新文章
- 2022-2028年中国商贸物流行业市场前瞻与投资战略规划分析报告
- 什么是条件组合覆盖_物史政组合分析,新高考最终受益者丨选科17期
- Windows下的磁盘管理(二)
- python应用于财务-用6行python代码做一个财务机器人
- java.lang.OutOfMemoryError及解决方案
- UIKIT网页基本结构学习
- 二叉树展开为链表—leetcode114
- Spring Bean的继承
- SSKeychain
- 【转】2.5SharePoint服务器端对象模型 之 访问网站和列表数据(Part 5)
- linux 批量进行:解压缩某一类压缩文件类型的文件
- 6 使用soap客户端_SOAP技术应用总结
- 摄影之构图,了解画面构成的五大元素:主体、陪体、前景、背景、留白
- 用hc05蓝牙模块,开发了几个安卓app了,越来越熟悉蓝牙app了。
- MIPI -- mipi_CSI-2_specification_v2-1-er01.pdf
- 电商基础知识:供应链产品介绍
- 数字 阅读与创造——读戴德金之三
- 什么是空指针?如何从根源避免空指针
- 【读书笔记】NeurIPS2018的两篇文章:The Tradeoffs of Large Scale Learning和Neural Ordinary Differential Equations
- 机器学习 笔记05——特征工程之特征处理:字典特征提取、文本特征提取
热门文章
- 中科院王晓群课题组建立血管化类脑器官培养新体系
- VMware三种网络模式配置详解。
- opencv 3 core组件进阶(2 ROI区域图像叠加图像混合;分离颜色通道、多通道图像混合;图像对比度,亮度值调整)...
- 集成底座项目实施总结
- 嵌入式学习笔记-2022.2.22
- 《五月集训》第二日——字符串
- 听说今年金三银四变成金一银二了。
- 〖Python WEB 自动化测试实战篇⑤〗- selenium 元素定位详解 - (八大元素定位方式)
- 微信公众号wifi链接php,TP路由器实现关注微信并认证后连接WIFI上网
- 手机格式化的计算机原理,格式化也不靠谱?教你如何彻底删除手机上的数据