一、 网络游戏开发的基本流程
◆ 项目文档
◆ 开发的进行和文档准备流程
◆ 技术人员文档
二、 MMO游戏架构
◆ MMO游戏特点
◆ MMO架构的特有内容
三、 策划文档
◆ 考虑示例游戏的题材
◆ 详细设计文档
◆ MMO庞大的游戏设定
◆ 5种设计文档
系统的基本结构图
进程关系图
资源评估文档
协议定义文档
数据库设计图
◆ 设计上的重要判断
四、 系统基本结构图
◆ 系统基本结构图的基础
◆ 服务器必须具有可扩展性 ---- 商业模式的确认
◆ 各瓶颈 ---- 扩展方式的选择
◆ MMO客户端特有的渲染性能瓶颈
◆ 解决服务器/数据库的瓶颈
空间分割法
实例法
平行世界方式
◆ 一台服务器负责整个游戏世界(什么都不做)
◆ 服务器的空间分割法 ---- 解决服务器的瓶颈
◆ 实例法 ---- 解决服务器的瓶颈
◆ 平行世界方式 ---- 解决数据库瓶颈
1、 同时采用平行世界和空间分割法
2、 同时采用空间分割、平行世界、实例法
◆ 同时采用多种方法 ---- 大量玩家在线时的数据
◆ 各种方式的引入难度
◆ 各个世界中数据库服务器的绝对性能提高
◆ K-Online的设计估算---- 首先从同时在线开始
◆ 据游戏逻辑的处理成本估算
◆ 据游戏数据库的处理负荷估算 ---- 角色数据的保存频率和数据库负荷的关系
◆ 可扩展性的最低讨论结果及进一步的用户体验追求
◆ 服务器的基本结构
五、 进程关系图
◆ 服务器连接的结构 ---- 只用空间分割法/使用平行世界方式和空间分割法
proxy与gmsv的关系是据gmsv处理逻辑的性能瓶颈和proxy连接数量瓶颈决定的m:n关系
(1) 只是用空间分割法;
蓝色是使用现有的服务器、黑色需要独立制作、准备
(2)同时使用平行世界和空间分割法
图 5-1-2-1 同时使用平行世界和空间分割法
使用平行世界方式进行扩展的关键是将dbsv分为dbsv1、dbsv2、dbsv3这样的多个数据库服务器,从而线性的提高存储游戏数据时的写入性能。
● authsv是共通的
● 分为5个平行世界,1个平行世界允许同时连接6000名玩家,总共允许3W玩家同时访问游戏
● 1个平行世界分为8个区(8核,8个进程)
● 1个平行世界准备360个实例(16核,
16个进程)
● 玩家继续增加的情况下,追加平行世界
图 5-1-2-1中,各个服务器的分布情况:
① 尽量使得authsv进程并行化
② 各个世界中,worldsv为1个进程,gmsv中地区用到8个进程,
实例用到16个进程,不能动态增减。
③ proxy与gmsv的个数相同
④ dbsv、MySQL、备份用的MySql每个世界1套
⑤ msgsv是所有世界共用的,尽量并行化,实际的进程数据要根据之后的基准测试来决定
⑥ logsv是所有世界共用的,只要1个进程,生成多少日志要在开发中决定
进程所需的服务器资源
进程 |
CPU(内核) |
备注 |
RAM |
||
存储器 |
||
TCP会话数 |
||
Gmsv |
W * (8 + 16) |
K-Online中的世界数据都是二维的,故数据量没那么大,内存每个内核1G就够,CPU成为性能瓶颈可能性高 |
上述 * 1G |
||
不需要 |
||
3+ |
||
Loginsv |
W * 1 |
通信缓存部分的内存,实际上loginsv很少成为瓶颈 |
上述 * 500M |
||
不需要 |
||
2+ |
||
Dbsv |
W * 1 |
通信缓存部分的内存,dbsv中的Mysql大多会成为瓶颈 |
上述 * 500M |
||
不需要 |
||
(8 + 16)+ |
||
Proxy |
W * (8 + 16) |
通信缓存部分是十分必要的,关键是TCP/IP的QPS性能可达到多少,但1个proxy只为1个gmsv,就不会成为瓶颈 |
上述 * 500M |
||
不需要 |
||
500+ |
||
Msgsv |
W * 2 |
对玩家的在线状况进行管理,防止二次登录,内存和CPU都可能以外的成为瓶颈,beta测试前要进行基准测试 |
上述 * 2G |
||
不需要 |
||
3+ |
||
Worldsv |
W * 1 |
因必须一定程度上把握各个gmsv的玩家状态,经常增加排序和搜索处理,故CPU和内存都容易成为瓶颈 |
上述 * 2G |
||
不需要 |
||
(8+16)+ |
||
Commondbsv |
1 |
平行世界方式下,进行与世界无关的持久化处理;存储设备更多地使用后端的Mysql,Mysql可能成为瓶颈 |
上述 * 500M |
||
不需要 |
||
W |
||
Authsv |
W * 1 |
只具有结算公司网关的功能,通信缓存部分的内存即可,authsv与结算公司间的线路延迟时,会成为瓶颈 |
上述 * 500M |
||
不需要 |
||
2+ |
Logsv |
1 |
不考虑日志存储量瓶颈,若gmsv等前端服务器突然发送大量日志,网络QPS会成为瓶颈 |
1G |
||
10T |
||
(10 + W * 30)+ |
||
Mysql |
W * 2 |
|
内核数 * 8G |
||
W * 100G |
||
1+ |
资源估算分为两大类型:CPU为中心的服务器、存储为中心的服务器
■ CPU为中心的服务器:
CPU较快,内核较多,内存一般,存储量少,容错性低,一次性的
■ 存储为中心的服务器:
CPU一般,内核一般,内存高,存储量大,容错性高,使用长期
◆ 使用平行世界方式进行扩展的关键
六、 资源估算文档
◆ 以进程列表为基础估算服务器资源
◆ 分别以CPU、存储为中心的服务器
◆ 服务器资源估算 ---- 成本估算
七、 协议文档
◆ 协议的基本性质
C/SMMO中,TCP的基础上构建专用的协议,协议的基本性质:
■ 哪些作为Server,哪些作为Client
■ 长连接还是短链接,取决于是否需强连网进行频繁的网络消息发送
■ 与服务器端间的会话是否是有状态的,是否要进行管理各个会话(例如:定期统计在线玩家人数,可做在Client与Server的连接之间)
■ 是否管理认证时的状态
■ Client与Server之间的,Server与Server之间的m
:n关系,取决于硬件系统和软件系统设计及处理的性能瓶颈的关系,例如:通常,一个Proxy远远满足于一个GameServer的处理性能需求
■ 是否需要服务器的主动推送(Push)
■ 连接中断时,是否需要立即结束服务
进程种类:
■ 客户端 cli
■ 逻辑服务器 gmsv
■ 登录服务器 loginsv
■ 消息服务器 msgsv
■ 数据库服务器 dbsv
■ 逆向代理服务器 proxy
■ 世界服务器 worldsv
■ 全体公用服务器 commondbsv
■ 收费认证服务器 authsv
■ 日志服务器 logsv
■ DBMS
■ 结算公司服务器 paysv
表7-1 进程间的关系
cli |
gmsv |
loginsv |
msgsv |
dbsv |
worldsv |
com-dbsv |
authsv |
logsv |
DBMS |
paysv |
|
cli |
● |
● |
● |
||||||||
gmsv |
● |
● |
● |
● |
|||||||
loginsv |
● |
● |
● |
● |
● |
||||||
msgsv |
● |
● |
● |
● |
|||||||
dbsv |
● |
● |
|||||||||
worldsv |
● |
||||||||||
com-dbsv |
● |
||||||||||
authsv |
● |
● |
|||||||||
logsv |
|||||||||||
DBMS |
|||||||||||
paysv |
协议性质划分原则:连到谁,就叫谁
■ gmsv协议
■ loginsv协议
■ msgsv协议
■ dbsv协议(gmsv、loginsv、msgsv都连接dbsv,就叫dbsv协议)
■ worldsv协议(gmsv、loginsv、msgsv都连接worldsv,就叫worldsv协议)
■ com-dbsv协议(gmsv、loginsv、msgsv都连接com-dbsv,就叫com-dbsv协议)
■ authsv协议
■ logsv协议(gmsv、loginsv、msgsv、dbsv、worldsv、com-dbsv、authsv)
表7-2 协议基本性质关系
Cli ① |
gmsv |
loginsv |
msgsv |
dbsv |
worldsv |
com-dbsv |
authsv |
logsv |
DBMS |
paysv |
||
Cli |
state n:1 push |
每次连接n:1 |
stateful n:1 push harmful |
② |
||||||||
Gmsv |
n:1 |
n:1 |
n:1 |
n:1 harmful |
||||||||
loginsv |
n:1 |
n:1 |
n:1 |
n:1 |
n:1 harmful |
|||||||
msgsv |
n:1 |
n:1 |
n:1 |
n:1 harmful |
||||||||
Dbsv |
③ |
n:1 harmful |
1:1 |
|||||||||
worldsv |
n:1 harmful |
|||||||||||
com-dbsv |
③ |
n:1 harmful |
1:1 |
|||||||||
authsv |
n:1 harmful |
n:1 |
||||||||||
logsv |
||||||||||||
DBMS |
||||||||||||
paysv |
state/stateful:需要服务器端管理各个会话的状态
push:需推送信息
harmful:连接中断时,不需要立即结束服务
表7-2各服务连接中断时,是否需要立即结束服务
① cli连接gmsv,连接中断时,MMO中是需要立即停止游戏的;但msgsv是聊天服务器,若出问题,游戏还是可以继续进行的,不需立即关闭客户端
② 各服务器间的连接,若前端服务器与后端服务器的连接中断或超时的情况下,前端服务器则停止运行。特别是dbsv异常的情况下,无法保存数据,若还是运行游戏,则产生与存储数据的不一致,这情况得避免,没有等待几秒重连的空闲
③ DBMS,authsv都是低频访问的服务器,则dbsv、authsv都得停止,而引起其余服务器都得停止
协议设计的基本原则:
■ 与后端服务器通信时,尽可能无状态;是可做到对于所有后端服务器无状态的
■ MMO系统,战斗、聊天服务器通常采用常连接,亦有使用到短链的场景
◆ 协议的API规范(概要)
协议的实现原则:
■ 后端Server实现基本的、通用的功能,前端Server实现专用功能,降低系统的修改成本,提高开发效率。但若在各自的进程中实现各项功能,即使发生内存访问冲突时,也能防止包含相关功能的部分同时崩溃,Google
Chrome采用的多进程就是出于这种考虑
■ 前端Server依赖于后端Server结构,位于后端的Server先启动,前端Server后启动
■ 协议是无状态和简单操作的集合,C/S MMO中,复杂处理集中在gmsv,可将有状态的协议限制在client与gmsv之间,除了gmsv协议,若有其他协议需要有状态,一般都是不合理的设计
■ 尽量在一个地方接受外部的异常情况,数据的持久化在一个地方进行,易于维护
■ 优秀的API的调用时序:最上最优
● 不调用API,即不需要;能做到不调用其他接口最好
● 只调用没有返回值的API的单向时序图(图7-3)
● 只调用一次然后获取返回值的呈三角状的时序图(图7-4)
● 呈锯齿状的时序图(图7-5)
gmsv采用比线程更轻量级的回调和任务系统实现异步编程,当C/S
MMO中出现“锯齿状时序图”时就需要对其必要性重新加以讨论;在处理互斥机制的部分时,采用“三角状时序图”或“线状时序图”来实现
图7-3 单向时序图
图7-3 三角状时序图
图7-4 锯齿状时序图
■ 是否有必要Push
◆ 协议的API规范(详细)
◆ 网络数据包格式
八、 数据库设计
◆ 数据库设计图
◆ 编码前的重要的表的设计
◆ K-Online所需的表
◆ 数据库性能测试
九、 C/S + 中间件
◆ 网络游戏的中间件
◆ MMO的基础支持单元
十、 开发中的基本原则
◆ 编程之始,编程之续
◆ 数据结构优先原则
◆ 实现数据结构之前的讨论
◆ 维持可玩的状态的原则
◆ 后端服务器的延后原则
◆ 持续测定的原则
GThinkServerEngine
Server_Gate
◆ complie : 编译和生成protobuf协议相关及.C文件
◆ config_server : 服务器配置
◆ console_mgr : 输入管理
◆ logger : 日志模块
◆ utility_game : 服务器ID相关函数
◆ globals : 全局接口、common库头文件,服务器状态
◆ service_mgr : 服务管理
◆ service_client : 面向客户端的服务
◆ service_login : 登陆验证的服务(应考虑独立出来)
◆ service_game : 面向游戏逻辑服的服务
◆ handle_service_client : 处理客户端的网络消息
◆ handle_service_login : 处理登陆的网络消息
◆ handle_service_game : 处理逻辑服的网络消息
◆ handle_server_performance : 处理qps等性能提升
Server_Game
◆ complie : 编译和生成protobuf协议相关及.C文件
◆ config_server : 服务器配置
◆ console_mgr : 输入管理
◆ logger : 日志模块
◆ utility_game : 服务器ID相关函数
◆ globals : common库头文件和全局的接口
◆ server_pool : 服务器Socket连接池
◆ suffix_trie : 敏感词过滤、后缀树
◆ json_help : json格式转换
◆ user_data : 玩家所有基类数据节点
◆ user_extend : 玩家数据节点扩展
◆ csv_storage : .csv配置文件的打开关闭、读写操作
◆ mail_template : 邮件模版
◆ client_layer : 验证客户端网络包的合法性及会话状态是否建立
◆ client_message_object : 解析客户端消息Object的相关操作:解包[获取msgID、获取msgData
+ len、获取client session info]、打包,encode + 加密 [rspData]
◆ client_session : 客户端会话的定义和操作,包含客户端的上下线信息及定时扫描
◆ client_session_mgr : 客户端会话管理,使用循环队列管理会话信息
◆ message_listen : 消息监听
◆ notify_system : 游戏内的服务器主动推送系统
◆ oss : 运营日志
◆ rpc_call_db : rpc调用数据库
◆ service_game : 面向server_gate服务器的连接等管理
◆ service_game_handler : 处理客户端的网络消息
◆ service_login : 登录流程的验证服务
◆ service_mgr : 逻辑服务器本身的网络和服务的管理,例如,服务的创建、网络的状态
◆ service_tool : 逻辑服务器要管理提供的服务的工具,针对其网络层和服务状态
◆ user_finger : 逻辑服务器中的金手指功能
◆ base_object/
游戏节点数据缓存机制:
game_object ---> CMemObject : 内存对象类
game_object ---> CGameObject : 游戏节点类
game_object ---> CGameObjectT : 游戏节点模版类
game_objectsT ---> CGameObjectsT : 游戏节点模版s类1,重载
game_objects2T ---> CGameObjects2T : 游戏节点模版s类2,重载
rich_user ---> CRichUser : 游戏玩家类,包含玩家所有基类节点的增删查改等操作;玩家所有基类数据节点放在user_data中
rich_user ---> IUser : 玩家的功能接口
注意:基类Set和Get的接口,仅限于到下一层的信息,接口层次统一,其他具体获取可放具体模块逻辑中。
IGameObject:声明CGameObject、CRichUser
IGameObject---> IGameObject : virtualvoid Release( ) = 0;
IGameObject---> IGameObjectBuilder :
■ virtualCGameObject* BuildObject(pb_common::xxxInfo&
info ) = 0;
GameObjectBuilder ---> CGameObjectBuilder:声明玩家所有基类节点CBasexxx,
提供生成和获取GameObject的Builder接口;
■ static IGameObjectBuilder*Builder(){return m_builer;}
■ static voidBuilder(IGameObjectBuilder* builder){m_builder =builder;}
■ 数据成员:
IGameObjectBuilder* m_builder;
游戏基类数据节点:
user_data ---> CUserData : 存放玩家所有基类节点数据
rich_user ---> CRichUser : 包含玩家所有基类节点的操作(对应client_rich_user)
base_users ---> CBaseUsers : 声明了CUserData、CRichUser;提供的接口:
■ void Load() : 玩家数据加载
■ void Save() : 玩家数据保存
■ bool SafeUpdate() : 安全更新玩家数据
■ bool SynUserData() : 同步玩家数据
■ void EnumUser() : 遍历玩家数据
■ 数据成员 :
pb_common::DataCtrl m_ctrl;
map<USERID, RichUserSPtr> m_users;
base_user_mgrT --->CBaseUserMgrT : 按标志Flag加载玩家数据节点及更新玩家数据
base_role --->CBaseRole
base_army_tech --->CBaseArmyTech
base_army_tech --->CBaseArmyTechs
base_bag_item --->CBaseBagItem
base_bag_items --->CBaseBagItems
base_battle --->CBaseBattle
base_enemy --->CBaseEnemy
base_enemys --->CBaseEnemys
base_friend --->CBaseFriend
base_friends --->CBaseFriends
base_manor --->CBaseManor
base_plant --->CBasePlant
base_plants --->CBasePlants
base_quest --->CBaseQuest
base_quests --->CBaseQuests
base_suit --->CBaseSuit
base_suits --->CBaseSuits
等都是挂载在User节点下的,而User的做法是将数据放在CUserData类中,将数据的操作放在CRichUser类中
最终,玩家所有节点数据派生为以GameObject为父类的子类,并且以模版类GameObjectsT和GameObjects2T的形式存储在内存中,提供GameServer全局的数据访问和修改的接口IGameObject。
节点数据生命周期中的轨迹图:
◆ codec : 网络层数据设计:数据包格式、解包和打包方式、加解密方式等
网络包消息格式定义:
--------4--------8--------12-------16------20-------24--------28
| | | | |
| |
|- MsgHead -| userid |- TokenBlob -|
EncodeBlob|
|- MsgHeadClientRequest -|
MsgHeadClientRequest -- MsgHead - hdr_len4Byte
| |
| - hdr_msg 2Byte
-- session 4Byte
|
-- userid 4Byte
|
-- TokenBlob - org_len4Byte
| |
| - mode 1Byte
-- EncodeBlob - checksum4Byte
|
- reqid 8Byte
--------4---------8--------12-------16
| | | | | |
|- MsgHead -| |EncodeBlob |
|- MsgHeadClientResponse -|
hdr_len 4Byte
hdr_msg 2Byte
result 2Byte
ogr_len 4Byte
mode 1Byte
◆ client_object/
client_game_object_builder--->CClientGameObjectBuilder
client_user_mgr --->CClientUserMgr
client_users --->CClientUsers
client_army_tech --->CClientArmyTech
client_army_techs --->CClientArmyTechs
client_bag_item --->CClientBagItem
client_bag_items --->CClientBagItems
client_battle --->CClientBattle
client_enemy --->CClientEnemy
client_enemys --->CClientEnemys
client_friend --->CClientFriend
client_friends --->CClientFriends
client_manor --->CClientManor
client_plant --->CClientPlant
client_plants --->CClientPlants
client_quest --->CClientQuest
client_quests --->CClientQuests
client_rich_user --->CClientRichUser
client_role --->CClientRole
client_suit --->CClientSuit
client_suits --->CClientSuits
Server_Redis_Cluster
Server_Redis_To_DB===>???(有没有更好的方法)
Server_Db_Cluster
Server_Common_DB ===>???(必要性)
Server_Login
Server_Auth
Server_Fight
Server_World
Server_Log
未完待续!待完善!转载必须附录原文地址:http://blog.csdn.net/itcombox/article/details/51445319