一、项目回顾
1 MMORPG项目
2.MOBA项目
二、服务器设计
服务器设计基础
1.核心需求
1.对于游戏服务器系统,表现的几个核心功能需求有:
- 存储游戏数据和玩家数据
- 对玩家客户端进行数据广播
- 把一部分游戏逻辑放在服务器上运算,防止外挂
2.核心设计
2.在服务器软件开发上,需要关注对电脑内存和CPU的使用,以求尽量满足承载量和响应延迟需求。基于此,服务器设计需核心考虑:
-
内存:
- 内存管理
- 内存池:避免频繁的内存分配和释放带来的性能开销。内存池的实现可以减少碎片化问题,提高内存使用效率
- 对象池:戏中大量的对象(如玩家、NPC、怪物等)可能是动态创建和销毁的,对象池能够重用对象,避免反复创建和销毁,减少GC(垃圾回收)的压力
- 内存对齐:确保内存的对齐方式能够提高缓存效率,减少访问延迟
- 数据结构设计
- 哈希表与字典:使用哈希表(如Redis、Memcached)存储频繁访问的数据(如玩家信息、物品状态、战斗状态等),能够在高并发环境下提供高效的查询性能
- 环形队列与缓冲区:处理大量的数据流(如网络数据包、事件处理),使用环形队列或固定大小的缓冲区可以有效地控制内存消耗和避免内存溢出。
- 缓存设计:游戏服务器通常需要高效的缓存层来存储共享数据(如玩家状态、排行榜)。使用分布式缓存系统(如Redis、Memcached)能提高访问速度并减少数据库压力
- 内存管理
-
调度:
- 设计如何使用进程、线程、协程这些对于CPU调度的方案。选择同步、异步等不同的编程模型,以提高服务器的稳定性和承载量。同时也要考虑对于开发带来的复杂度问题
-
通信模式
- 决定使用何种方式通讯。网络通讯包含有传输层的选择,如TCP/UDP;据表达层的选择,如定义协议;以及应用层的接口设计,如消息队列、事件分发、远程调用等
3.游戏服务器的分区设计
- 分服制(区服),玩家选择特定服务器,数据隔离
- 单服大世界(分线制),逻辑单世界,物理多分线
- 全区全服,所有玩家在同一个逻辑世界,无服务器分割
- 区域制(地理分服)
- 房间服务器
4.游戏类型分类
- 根据游戏方式分类
- MMORPG,大型多人角色扮演游戏,魔兽世界、梦幻西游。游戏特征,整个游戏是一个大世界,这类游戏添加很多社交元素:公会,好友。。。
- MOBA(Multiplayer Online Battle Arena),多人在线战术竞技游戏,游戏特征,以消灭对方队伍的阵地建筑为胜利条件。《Dota2》、英雄联盟、王者荣耀
- MMOG(Massive Multiplayer Online Game),指任何网络游戏的服务器可以提供大量玩家同时在线的游戏,相对其他类型游戏:竞技游戏,网页游戏,小游戏等
- 根据游戏玩法分类
- ACT(Action Game)动作游戏,包括射击游戏(STG,shooting game)和格斗游戏(FTG,fighting game),FPS射击类游戏(第一人称射击游戏)
- RPG(Role play game)角色扮演,ARPG,动作角色
- SG(Strategy Game) 策略游戏
- SLG(simulation game)模拟游戏
- AVG(adventure game)冒险游戏
- RG(Race game)竞速游戏
5. 一些游戏分析
* 通常大型游戏MMO带有养成类与人竞争的游戏,为了避免新玩家被老玩家吊打,需要分服。
* 原神是纯单机,最多也就支持4人同场景,没有任何交互压力,服务器也没有什么重度业务逻辑,所以也可以做成全区全服
* 魔兽世界的中无缝地图,整个世界的移动没有像以往的游戏一样,在切换场景的时候需要loading等待,而是直接行走过去,体验流畅。现在的游戏大地图采用无缝地图多数采用的是9宫格的样式来处理,由于地图没有魔兽那么大,所以采用单台服务器多进程处理即可(传奇,Word1,Word2...),不过类似魔兽世界这种大世界地图,必须考虑2个问题:
* 1.多个地图节点如何无缝拼接,特别是当地图节点比较多的时候,如何保证无缝拼接。
* 2.如何支持动态分布,有些区域人多,有些区域人少,保证服务器资源利用的最大化。
无缝世界并不存在一块地图上面的人有且只由一台服务器处理了,此时需要一组服务器来处理,每台 Node服务器用来管理一块地图区域,由 NodeMaster(NM)来为他们提供总体管理。
* **Node服务器**:每台Node服务器独立管理一个地图区域的状态,包括玩家位置、物理计算、NPC行为等
* **NodeMaster(NM)** :NodeMaster是一个中央管理节点,负责整个游戏世界的节点协调。它的职责包括:
动态分配负载:当某个节点的负载过高时,NodeMaster可以根据需要将部分玩家移到负载较轻的节点。
节点状态同步:NodeMaster负责收集各个Node的状态信息,确保所有节点之间的行为一致。
数据一致性维护:NodeMaster确保每个节点的数据在跨节点的玩家移动过程中保持一致。
* **边界数据同步**:当玩家从一个地图节点走到另一个节点时,当前节点和目标节点的服务器会同步彼此的游戏状态、物理环境、地理数据等。这确保玩家在地图节点之间切换时不会感知到“断裂”或“加载”。(注意释放数据)
* **动态区域调整与负载均衡**:
<!---->
负载监控:NodeMaster实时监控每个Node的负载情况(如玩家数量、计算资源使用、网络带宽等),确保负载较高的区域获得更多的计算资源。
动态资源调配:当某些区域的玩家数量过多时,NodeMaster可以指示增加新的Node服务器,或者将一些玩家迁移到负载较轻的区域。
6.服务器功能
- Loin:登陆服,创角,进行登陆,验证成功后,返回网关信息,同时会将玩家登陆的token 放到Gate服。然后玩家连接Gate服登陆到Game服。
- Gate 网关服, 管理所有的连接,负责解析数据包、加解密、超时处理和一定逻辑处理,这样可以提前过滤掉错误包和非法数据包,转发消息到对应的服务器,比如移动消息发送到场景服,玩家的升级操作发到游戏服。逻辑也相对比较简单。
- Game:游戏服(场景服),游戏服是承载所有游戏逻辑的服务器(游戏大厅),副本的逻辑
- Room:房间服,或战斗服,房间结束之后把战斗结果传到游戏服进行判定,进行发奖等逻辑
- DBServer:存取数据
- CenterSerer:中心服(管理服),处理内部服务器之间的消息转发,和某些转发流程控制。
中心服务器是个单点,维护着区服信息、节点信息、配置信息,用于其他服务器来进行读取.
只有当中心服务器启动后,其他服务器才能启动并注册上去。
中心服务器在运行过程中,会与其他服务器进行PING,来保持连接,并且收集运行状态。
中心服务器挂了后,其他服务器不会挂,只是不能支持新服务器启动与配置。
中心服务器配套一个可视化的控制台,用于架构全面监控与控制。
7.状态同步和帧同步
- 状态同步的战斗逻辑在服务端,在状态同步下,客户端更像是一个服务端数据的表现层,举个例子,一个英雄的几乎所有属性(例如血量、攻击、防御、攻速、魔法值等等)都是服务端传给客户端的,而且在属性发生改变的时候,服务端需要实时告诉客户端哪些属性改变了,客户端并不能改变这些属性,而是服务端传来多少属性就显示多少属性(虽然可以改变客户端数值达到表现上的效果,例如无限血量,但是服务端那边的血量属性为0时,一样要死)
服务器维护游戏的“权威状态”(如所有角色的位置血量动画状态)
服务器定期将这些状态数据同步给所有客户端
客户端只做渲染和简单预测,主要以服务器下发的状态为准
- 帧同步的战斗逻辑在客户端,在帧同步下,通信就比较简单了,服务端只转发操作,不做任何逻辑处理
状态同步不太适合用来做实时竞技游戏.因为虽然客户端也会有各种各样的预测技术,服务器计算也需要时间。而帧同步比较适合,因为它所有的运算都是在客户端进行模拟的,服务器没有做任何的运算,只是做个消息的转发,所以服务器没有什么运算的压力,全部都在客户端运算
架构设计
1.设计原则
1.架构设计遵循原则:可扩容,可容灾,高可用
2.经典的软件架构描述\
2.结构分析
软件架构的分析,可以通过不同层面理解:
- 运行时架构:关注如何解决运行效率问题,通常以程序进程图、数据流图为表达方式。
- 逻辑架构:关注软件代码之间的关系,以类图、模块图的表达方式。解决软件的可拓展性和可重用度问题的设计。
- 物理架构:关注软件如何部署、以机房、服务器、网络设备为主要描述对象
- 数据架构:关注数据结构的设计,对于数据分析挖掘有较大意义
- 开发架构:关系开发库之间的关系,以及版本管理、开发工具、编译构建的设计
3.服务器模型选择
- 单进程游戏服务器(单进程单线程只能使用一个CPU,不能充分利用CPU资源)
- 异步-多线程:epoll+ 3类线程(主线程+IO线程+逻辑线程),线程之间通过无锁消息队列通信
- 多进程游戏服务器架构(单进程架构下,总会存在承载量的极限)
- 每个模块的功能,都单独开发成一个进程,然后以使用进程间通信来协调处理完整的逻辑
4. 运行时架构
5. 服务之间的消息流
- client 和GameServer、RoomServer直连,缺少独立网关的设计的考虑点是 减少一层转发,降低延迟,尤其房间战斗服需要低延迟。