KBEngine技术概览开源游戏服务端引擎概要KBEngine服务器概览实现一个EntityEntity的通信Entity核心部件Cell功能集服务器设置和维护服务器调试服务器的profiling和压力测试第一章KBEngine服务器概览KBEngine服务器架构ClientClientClientSwitchFabricInternetSwitchFabricLoginappLoginappBaseappBaseappBaseappCellappCellappCellappBaseappMgrCellappMgrDBMgrDatabaseCellappCellapp同时每台硬件机器需要运行守护进程machineLoginapp进程与客户端的第一个连接点固定的端口初始通信时加密公用密钥对(任意长度的密钥)用户名/密码使用多个Loginapps使得负载均衡DNS轮流调度Baseapp进程与客户端通信的固定点客户端与Cellapp通信的中介与客户端的连接均衡地分担在各Baseapp间用于处理没有空间位置属性的Entity拍卖行公会管理管理器每个Baseapp同时担任着为其它Baseapp容错的角色通常一个CPU/核上处理一个BaseappBaseEntity(实体)Baseapp上有两种实体BaseProxyBase通常的游戏Entity例如:存储在数据库里的NPC,拍卖行…Proxy与客户端连接C++继承自KBEngine.Base特殊的BaseBaseapp容错处理备份entity到其它的BaseappsBaseappBaseappBaseappBaseapp自己的Base实体其他Baseapp上的base实体的备份Baseapp容错处理Baseappcrash后变得不可用BaseappBaseappBaseapp自己的Base实体其他Baseapp上的base实体的备份Baseapp容错处理灾难发生后快速切换到其他备份的BaseappBaseappBaseappBaseapp自己的Base实体其他Baseapp上的base实体的备份Baseapp容错处理与Crash的Baseapp连接的客户端会被断开连接所有的数据都被存储了当重新连接后,它们将继续与其原来的Entity连接(如果没有timeout的话)Baseapp的管理器(BaseappMgr)负责管理Baseapp间的负载平衡监视所有的Baseapp以实现各个Baseapp之间的容错主要用于玩家登录分配和创建Entity一个服务器群组有一个BaseappMgr实例Cellapp进程空间与位置数据的处理处理玩家交互的Space(空间、房间、场景…)处理在Space内的Entity处理Space内的一个区域(Cell)一个Cellapp在一个Space上的Cell只会有一个(通常进程占用一个CPU/核,多个Cell并没有意义)一个Celapp有可能处理多个Space通常一个CPU/核上处理一个CellappCells&Spaces目前不支持Space拆分成多个Cell由Cellapps共同负载,因此本页可忽略Spaces通过Cells来实现平衡负载每个Space至少含有一个Cell每个Cell处理Space的一个区域Cell的边界根据Cell的负载而移动Cells不影响客户端的游戏体验Cell1Cell2Cell3Cell4Cell5Cell6一个Space被拆分成多个CellCellapp主要负载的地方管理的Entity的总数量Entity的通信的频率用户所调用的方法系统自动更新的属性Entity的密集度Entity脚本Entity的数据大小Entity与Cell每个space至少有一个Entity通常第一个Entity是SpaceEntity,用于让用户操控SpaceCellApp上的每个玩家Entity都有一个Witness对象Witness监视周围的Entity,将发生的事件消息同步到客户端Entity的兴趣范围(AOI)缺省是500M是可以自定义的,依赖于很多因素Entity与Cell(本页跨Cell内容未实现)Entity穿越Cell边界是无缝的客户端不会感觉到(穿越边界的发生)每个Cell维护着一个list,存放着在其边界外沿的EntityGhostentities半径500m,可配置大于等于AOICell1Cell2500mradiusRealEntityGhostEntity500mboundaryregion500mboundaryregionEntity:Real与GhostRealEntity是权威的Entity一个GhostEntity是从邻近的Cell的对应的Entity的部分数据的拷贝Cell1Cell2500mboundaryregion500mboundaryregionRealEntityGhostEntityGhostEntity解决跨越Cell边界的Entity的交互问题方法调用转发给其RealEntity属性一个属性可以是realonly的,例如:将永远不会存在于ghost上如果一个属性对于客户端是可见的,那么该属性必须是可以ghost的,例如:当前的武器、等级、名称Ghost属性是只读的要更改属性值只能通过方法调用来更新其对应的RealEntityEntity的数据更新客户端实现LOD以加速渲染Cellapp实现LOD以减少:带宽的消耗每个Entity的CPU消耗LOD在Cellapp上的作用类似于在客户端的作用细节程度是相对于玩家entity与之的距离的客户端Entity方法可以实现LODEntity属性实现LOD可以避免不必要的通信到客户端当前的血量(对于很远的距离(的Entity)来说是不可见的)Cellapp管理器(CellappMgr)CellappMgr知道:所有的Cellapp(及它们的负载)所有的Cell边界所有Space管理Cellapp的负载平衡告诉Cellapp们它们的Cell边界应该在哪里把新建的Entity加入到正确的Cell上一个服务器群组一个CellappMgr实例数据库管理器(DBMgr)管理Entity数据的数据库存储负责数据库与其余的服务器间的Entity信息的通信支持的数据库类型:MySQLMongoDBRedis…你自己定制最好独立的机器运行Entity备份存档在Baseapp间轮流调度处理Baseapp向Cellapp要Entity的Cell部分的数据再定时转给DBMgr存储KBEngine的机器Daemon(machine)Daemon用于监视服务器进程每个服务器机器上有一个machine启动/停止服务器进程通知服务器群组各个进程的存活状态监视机器的使用状态CPU/内存/带宽KBEngine服务端通常的操作一个Baseapp,2个及以上Cellapp不同游戏不同情况早Profile,经常Profile情况允许,应放在独立的机器的进程:DBMgr一些工具类进程登录过程客户端发登录请求指定IP/端口Loginapp收到登录请求解密请求消息(一些客户端也会选择不加密通讯,那么服务端不进行解密)Loginapp转发登录消息到DBMgrDBMgr验证用户名/密码查询数据库转发请求到BaseappMgrBaseappMgr发送创建PlayerEntity的消息到负载最小的BaseappBaseapp创建一个新的Proxy可能会创建一个新的CellEntityProxy的TCP端口被返回给客户端途径BaseappMgr,DBMgr,Loginapp第二章实现一个Entity游戏项目资产库KBEngine引擎默认资产库如果用户没有设置环境变量指向,引擎默认会尝试读取引擎根目录assets作为默认的资产库资产库的概念类似于Unity3D中的Assets,不过其中一些文件夹名称结构被固定了不同的项目是不同的资产库要想引擎启动时读取到对应的项目资产库,必须在环境变量中制定*.py自定义类型脚本资产库文件夹结构列出了所有的entity定义Entity的属性和方法(XML)实现属性和方法(Python)assetsscriptsentities.xmlbasecellcliententity_defsentity.pyBaseapp脚本entity.pyCellapp脚本entity.pyClient脚本(只在包含Python解析器的原生环境有效,Unity3D等插件环境不需要在此实现)entity.def定义文件common*.py公用的scriptCell,Base,Client相互之间共用的实现函数server_common*.py公用的scriptCell,Base相互之间共用的实现函数user_typeres资产库文件夹结构assetsscriptsdatadbbotsserverspaceskbengine.xml服务端配置文件空间的资源数据,例如:提供实体服务端导航的碰撞信息res服务端逻辑数据文件,例如:策划导表数据数据库扩展机器人压力测试,虚拟客户端脚本,可以简化scripts/client下的脚本实现Entity的实现每个Entity必须:在entities.xml文件的列表里必须有一个Entity_name.def文件必须有Entity_name.py文件每个Entity可以:有最多3个部分的实现(Client/Cell/Base)使用common路径下的共享的脚本Client/Server的定义文件必须匹配在一下插件环境,插件会根据协议MD5保证协议是最新的,当协议不匹配时会从服务端网络导入并存储到本地分布式的EntityBaseEntityRealEntityGhostEntityPlayerEntityClientEntityBaseappABBaseappCClientAClientBClientCCellapp1-cell1ABCellapp2-cell2CCellapp3-cell3ABCABCSpace1-Cell1Space1-Cell2Space1-Cell3ABCABBCACAB在一个space上CABC分布式的EntityCellApp1,CellApp2和CellApp3都各自有一个Space1的Cell三个EntityA,B和C都在Space1Cellapp1ABCellapp2CCellapp3ABCABCSpace1-Cell1Space1-Cell2Space1-Cell3ABCAB在一个space上CABC分布式的Entity-从Cellapp1来看Space1的CellApp1的Cell:A和B是RealEntityC是一个从CellApp2上ghost来的ghostEntityCellapp1ABCellapp2CCellapp3ABCABCSpace1-Cell1Space1-Cell2Space1-Cell3ABCAB在一个space上CABC分布式的Entity-从Cellapp2来看Space1的CellApp2的Cell:C是RealEntityA和B是一个从CellApp1上ghost来的ghostEntityCellapp1ABCellapp2CCellapp3ABCABCSpace1-Cell1Space1-Cell2Space1-Cell3ABCAB在一个space上CABC分布式的Entity-从Cellapp3来看Space1的CellApp3的Cell:A和B是一个从CellApp1上ghost来的ghostEntityC是一个从CellApp2上ghost来的ghostEntityCellapp1ABCellapp2CCellapp3ABCABCSpace1