-
Notifications
You must be signed in to change notification settings - Fork 2.9k
LordOfPomelo 服务器介绍
LordOfPomelo采用分布式的设计, 服务端是由一个服务器集群组成的, 包括:多台场景服务器, 一台或多台寻路服务器, 聊天服务器, 副本/组队服务器, 全局服务器, 长连接服务器等.
与web的短连接模式不同, 在网络游戏中客户端与服务端建立的都是长连接. 而长连接本身是需要一定的资源来维持的, 在LordOfPomelo中, 我们使用websocket协议在客户端和服务器之间建立连接. 而connector服务器就是用来维护这些连接, 并中转客户端和服务端之间的消息. 在LordOfPomelo中, 客户端和服务端的连接状态是通过一个抽象的session来维护的, session是一个客户端在服务端的标识, 用来维护用户的登录状态, 用户的基本信息, 以及用户的websocket连接信息.
gate服务器的主要作用是为用户提供一个统一的websocket入口, 并负责用户验证和connector服务器的分配. 与connector服务器不同, LordOfPomelo中只有一台gate服务器. gate服务器会向所有客户端暴露一个固定的websocket接口, 当用户登录时, 会首先连接gate服务器, 完成验证, 并获得由gate服务器分配的对应connetor服务器的信息. 之后, 客户端会断开与gate服务器的连接, 通过获取的信息连接对应的connector服务器, 获取对应的服务.
验证服务器负责用户注册和验证. 作为用户验证的统一入口, 提供远程调用接口供其他服务器调用, 来进行用户的验证. 验证服务器的主要作用是屏蔽认证验证的细节, 为其他服务器提供统一的验证接口.
在网络游戏中, 出于性能和负载的考量, 大的游戏世界总是会被分成多个区域, 这些不同区域就是场景. 在LordOfPomelo中, 一张游戏地图就是一个游戏场景, 与一台独立的场景服务器对应. 场景是构成LordOfPomelo游戏世界的基本单位, 不能进行分割和简单的并行扩展. 场景服务器负责维护场景中所有实体, 并驱动实体AI运行游戏逻辑.
场景服务器负责处理游戏中的几乎所有逻辑, 同时为其他服务器提供操纵场景数据的接口. 在LordOfPomelo中, 虽然场景本身不能分割, 但可以通过加入新的游戏场景的方法来分散用户, 从而提高游戏服务器总的负载量. 而一些与场景相关的服务也可以通过独立运行的方式进行水平扩展.
寻路服务是游戏服务器的基本服务之一, 玩家跑动, 怪物移动都需要寻路服务提供支持. 其功能是根据地图中的起点和终点, 得到一条这两点之间的最优路径. 由于寻路是典型的无状态、计算密集型服务, 在LordOfPomelo中, 我们将寻路逻辑与场景逻辑分离, 放在单独的寻路服务器中, 从而减轻了场景服务器的压力. 而寻路服务器也可以根据需要进行简单的并行扩展. LordOfPomelo中的寻路算法使用A*实现, 提供了通用的计算接口, 并封装为一个模块, 具体信息见pomelo-pathfinding.
聊天服务是网游的基本服务之一. 在LordOfPomelo中, 聊天服务是与场景服务分离的, 通过一个独立的服务器来实现. 聊天服务器会维护一份所有在线用户的数据, 通过这些数据与connector服务器通讯, 来实现玩家之间的即时通讯.
副本/组队服务器是后端服务器集群中负责全局管理副本全生命周期和组队相关操作的功能服务器.具体可参考lordofpomelo 0.3新特性
LordOfPomelo中的场景服务负责管理游戏中所有实体和整个游戏世界. 而出于安全性和一致性等方面的考虑, 所有的游戏逻辑验证都是在后端进行的, 因此场景服务还包括了游戏中所有的逻辑判断和处理. LordOfPomelo的场景服务是游戏服务的核心, 也是逻辑最为复杂的部分, 下面就对LordOfPomelo中的场景服务进行分析:
LordOfPomelo中每个场景对应一个独立的场景服务器, 所有的业务逻辑都在场景服务器内部进行. 对于跨场景的操作, 则是通过一个全局服务器来进行处理. 下图就是一台单独的场景服务器的功能:
游戏场景中的所有实体都会在进入场景时加载到内存中, 之后所有的修改都会直接在内存中进行, 并通过数据同步模块来定时同步到数据库中. 这一设计将场景中所有的数据操作都变成了直接的内存操作, 提高了整体性能, 规避了频繁的缓慢IO操作.
LordOfPomelo中实体的定义都在domain目录下的entity文件夹中, 采用了面向对象的设计思想, 所有实体都继承自entity类. 实体的加入和删除都通过area中的接口(addEntity/removeEntity)来处理, 从而减轻了对象的管理负担.
LordOfPomelo中的消息服务可以分为两种:一对一的RPC请求<-->响应, 以及一对多的广播消息. 由于LordOfPomelo中的逻辑验证是在服务端进行的, 对于客户端的大部分请求, 服务端都会有一个直接的回复来进行处理, 这种回复是使用了类似于web中的request/response模式来实现的.
对于广播服务, LordOfPomelo中使用了基于AOI的区域通知服务. 即在收到广播消息后, 根据消息类型, 通过AOI服务获得需要通知的玩家列表, 然后对该列表中的玩家进行广播, 从而大幅减少了消息的数量.
玩家的视野一般远小于场景的大小, 因此对于场景中的绝大部分消息, 进行简单的全场景广播是没有必要而且无法承受的. 当有消息需要发送时, 如何确定该消息需要通知的玩家列表就是AOI模块的功能了.
LordOfPomelo中实现的是基于灯塔的AOI服务. 其基本的实现方法是将整个地图划分为若干个等大的tower, 每个tower负责维护一个对象列表, 指向所有在这个tower范围内的对象. 然后在这个数据结构的基础上来触发各种AOI事件.