饭宝 发表于 2025-4-14 22:44:56

MMO 架构梳理

简便 MMO 架构

                              ┌───────────────┐               ┌───────────────┐
          ┌────────────────────►│      SLB      ├────────────────►│   Login   │
          │         http      └───────────────┘               └───────────────┘
          │
          │
          │
          │
          │
          │
          │
          │
          │
          │
          │
┌─────────┴─────┐   tcp         ┌───────────────┐               ┌───────────────┐
│    Client   ├──────────────►│      SLB      ├────────────────►│    Gateway    │
└───────────────┘               └───────────────┘               └───────┬───────┘
                                                                        │
                                                                        │
                                                 ┌────────────────────────┼──────────────────────┐
                                                 │                        │                      │
                                                 │                        │                      │
                                                 ▼                        ▼                      ▼
                                          ┌---------------┐       ┌───────────────┐      ┌---------------┐
                                          │    Lobby      │       │   Game      │      │      Mng      │
                                          └---------------┘       └───────────────┘      └---------------┘



                                          ┌──────────────────────────────────────────────────────────────┐
                                          │                                                            │
                                          │ db   ┌───────────────┐            ┌───────────────┐      │
                                          │      │    DBProxy    │            │   Redis   │      │
                                          │      └───────────────┘    OR      └───────────────┘      │
                                          │      ┌───────────────┐            ┌───────────────┐      │
                                          │      │   MySQL   │            │   MySQL   │      │
                                          │      └───────────────┘            └───────────────┘      │
                                          │                                                            │
                                          └──────────────────────────────────────────────────────────────┘
服务功能其他说明Login鉴权服经典的 MMO 一般会有 Lobby 服,紧张是获取角色列表、创角、删角等使用。可以归并到 Login 服Gateway会话服Game功能服、场景服Mng服务治理服列出来方便明白,本质上这个 Mng 存在单点、热点题目,因此实操会优化为 Redis 代替DBProxyDB 代理服经典的 MMO 一般会有 DBProxy + MySQL ,可选方案 Redis + MySQL 。见后详细说明 服务治理服 Mng

如上所述,该服会被优化掉,但是功能、概念仍然存在,包括:


[*]服务依赖
[*]服务发现
[*]负载均衡
[*]场景舆图管理
服务依赖
服务依赖,不是功能,是项目服务间依赖关系的一种客观事实形貌
这样每个进程可以对自己感爱好的服务,收集服务信息
服务发现

[*] 每个服务进程对 Redis 定期续租

[*]如 Key 为 Servers ,范例 HMAP
[*]定期 HSET serverID serverInfo ( serverInfo 至少包含 serverType serverActiveTime )

[*] 每个进程定期拉取 Servers ,对感爱好的服务信息和本地做 diff,进而知道服务新增或失效
负载均衡
以场景分配举例:

[*]Gateway 会定期拉取 Servers
[*]每个服务会给依赖它的服务发送实时 serverInfo 变化信息

[*]如, Game 的 serverInfo 还会包含场景个数信息

这样 Gateway 本地就可以实时缓存 Game 的 serverInfo
对于玩家登录, Gateway 就可以本地负载均衡 Game
场景舆图管理
比如无缝大世界,会做舆图切块,让差别 Game 只负责该切块上的玩家
也有游戏全部场景单 Game 上构建,内存支撑不了,也会做差别 Game 负责一组场景的需求
有这类功能的, Mng 都必须存在,做场景分配的调度中央
登录


[*]client 找 login 鉴权
[*]login 下发 gateway 地点和 token
[*]login 连接 gateway,发送登录 token
[*]gateway 验收 token,并分配 Game
分配 Game 见背面详细说明
登出


[*]角色信息记载末了登出的 LastGame 和 LogoutTime
[*]本地角色对象,删除
[*]本场景对象内人数为 0 后

[*]单人本,删除
[*]多人本,可耽误几分钟删除

本地 DB 数据缓存

通常直接做进 DB 层,让开发者无感知
但是架构计划者需要知晓
由于,分配服务时,需要命中带缓存的那个服务
登录分配 Game

Game 会缓存角色数据、场景数据,玩家下次登录在缓存有效的环境下,应该进原来的 Game
那么分配 Game 逻辑就变为:


[*]实验获取角色末了登出的 LastGame 和 LogoutTime
[*]如果 LastGame!=0 ,且 LogoutTime 小于本地缓存时间隔断(最好再大些),检查末了登出的 LastGame 是有效的:

[*]不需要做什么

[*]否则,Gateway 随机分配 NewGame ,让 LastGame = NewGame
[*]登录 LastGame
以上逻辑一般基本够用,如果是超级严谨派程序员,照旧能看出上面算法存在的 1 个并发登录题目:
当同账号多端互踢:


[*]端1 登录,连接了 Gateway1 发送登录哀求。这时 Gateway1 执行登录逻辑
[*]端2 登录,连接了 Gateway2 发送登录哀求。这时 Gateway2 也并发的执行登录逻辑
[*]虽然 2 次登录 Login 分配了 2 个 token
[*]但是 2 个 Gateway 并发登录,没有跨进程锁登录过程,是有概率让 2 个 token 都能验证通过
[*]进而造成同个角色被分配了 2 个 Game 的 bug (2 个 Game 上都有该角色数据缓存,可能会出现回档题目)
因此更严谨的分配 Game 逻辑就变成:


[*]实验获取角色末了登出的 LastGame 和 LogoutTime
[*]如果 LastGame!=0 ,且 LogoutTime 小于本地缓存时间隔断(最好再大些),检查末了登出的 LastGame 是有效的:

[*]不需要做什么

[*]否则,Gateway 随机分配 NewGame ,让 LastGame = NewGame
[*]Redis GetSet LastGame:RoleID LastGame ,抢占 LastGame ,返回实际 LastGame2
[*]登录 LastGame2
即增长了Redis GetSet 抢占 LastGame ,返回实际 LastGame2,保证不管任何并发环境,分配的 Game 是一样的
Game 的登录逻辑中:


[*]发现有旧的 Gateway ,发送踢旧 Gateway 角色,这样多并发下,最终只会有 1 个 Client 到 Gateway 到 Game 的链路
[*]创建角色对象。未有缓存数据,则 db 加载数据
[*]续租 LastGame:RoleID ,这样断线重连等, Gateway 按上述算法,会登录当前 Game
[*]创建或进入场景

[*]如果是单人本、或者公共舆图,一般只要带上 MapCfgID 即可
[*]如果是多人本,一般需要带上 MapInstanceID

创建或进入场景



[*]Game 上本地 SceneMng 创建或获取场景对象

[*]创建的,还需要实验从 DB 种加载场景玩法数据
[*]如果是多人本,发现 MapInstanceID 不存在,则给对应 Gateway 发送踢人(切换场景和登录并发时会出现)

[*]如果是多人本,广播 Gateway 信息 MapInstanceID - Game
[*]玩家到场场景,触发 AOI 消息等等
场景切换

Client 发送切换场景到 Gateway :
如果是以下 2 种环境:


[*]如果是单人本、公共舆图
[*]如果是多人本,且根据 MapInstanceID 和 Redis GetSet 下得到是同个 Game
回复 Client OK ,并转发切换场景给 Game ,Game 本地场景切换逻辑
如果 Gateway 确定是差别的 Game :


[*]关照旧 Game 角色登出删缓存
[*]如果是多人本,强行过期设置 Redis Set LastGame:RoleID NewGame
[*]回复 Client Relogin
[*]断开 Client 连接
[*]Client 重新登录
1端登录、1端切换场景并发会不会有题目
上述切换场景流程里的逼迫设置 LastGame:RoleID ,破坏了租约机制,不会有题目
答案是安全的,原因如下:


[*]如果是单人本、公共舆图,同个 Game
[*]如果是多人本,1 端并发登录到旧 Game ,该 Game 会发现 MapInstanceID 不存在,给对于 Gateway 发送踢人
多人本切换场景, MapInstanceID 必不为 0
切换的前提是该场景事先已创建,如何实现创建,需要走具体业务逻辑
如组队本,队长地点服会创建进入,再关照其他 Client MapInstanceID 信息
DBProxy 服

DBProxy + MySQL 紧张作用之一是充当热数据缓存,如果你引入 DBProxy 只是为了办理 MySQL 读写慢题目。发起可以直接使用 Redis + MySQL
假设你想添加一些更高级的 DB 功能,DBProxy 服则更得当
FAQ



[*]登录并发这里为啥不用分布式账号锁,而用抢占式+续租方式

[*]分布式账号锁有过期时间,Gateway 宕机等,会造成短时间内账号无法登录


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: MMO 架构梳理