拓扑评审通过之后
卷一的最后一次评审会上,三款产品的拓扑都定了:竞技走大厅加房间,SLG 走全球同服加地域分片,休闲走模块化单体。会议室里的人松了一口气,仿佛最难的部分已经过去。
真正的麻烦从第二天开始。
客户端问:登录票据多久过期,断线重连要不要重新登录。运营问:补偿邮件由谁发,发重了怎么办。平台团队问:匹配算法是平台提供还是每个游戏自己写。财务问:渠道回调重复时,充值到底记几笔。运维问:玩家说奖励没到账,我去哪张表里查。
这些问题的共同点是:它们不属于拓扑,却决定了拓扑能不能落地。 拓扑回答“服务怎么摆”,系统契约回答“服务之间怎么约定”。前者错,后面很难补救;后者错,系统会以一种看似正常的方式持续产生错误数据。
这就是卷二要处理的问题。
卷一与卷二的分工
卷一讨论的是可行域:品类事实如何压缩拓扑选择,状态、时间、连接、权威应该放在哪一层。它刻意不展开具体系统,因为系统实现依赖拓扑,顺序反了会把结论写死。
卷二进入系统层,但也不是实现教程。它讨论每个核心系统的边界、契约与失败模式:
| 问题 | 卷一 | 卷二 |
|---|---|---|
| 账号 | 不属于拓扑议题 | 账号、角色、设备、租户怎么分层,外部身份怎么映射 |
| 登录 | 连接模型的一部分 | 票据、续期、吊销、排队与洪峰 |
| 房间 | 拓扑与故障域 | 生命周期、幽灵房间、实例分配与暖池 |
| 战斗 | 权威模型 | 战斗服形态、结算契约、日志与回放 |
| 经济 | 状态归属 | 账本、交易托管、风控指标 |
| 平台 | 只提了一句 | 能力边界、租户隔离、SLA 与产品契约 |
与《MMO 服务器开发》的分工同样明确:那套书回答“这套系统具体怎么写”,本书回答“为什么这样切、契约定在哪、失败时谁负责”。遇到协议编解码、AOI 数据结构、技能系统的实现细节,正文会用一段话概括,再用站内链接指回对应章节。
三个反复出现的问题
问题一:这份数据到底归谁
几乎每个跨团队事故,最后都能追到同一句话:这份数据到底归谁。
账号服务存了角色列表,游戏服也缓存了一份;订单服务写了支付状态,游戏服又根据回调改了一次;平台统计了在线人数,网关也维护了一张连接表。两份数据在平时看起来一致,一出故障就分叉,而且没人能说清哪份是对的。
卷二会给每个核心系统写一张“所有权卡”:它拥有什么数据、谁可以写、谁只能读、保留多久、删除时由谁负责。所有权不是文档里的形容词,它要能落到唯一约束、写入接口和越权检测上。
问题二:失败时谁兜底
分布式系统里,“成功”只有一种,“失败”有很多种:超时但实际成功、回调重复、消息丢失、消息乱序、部分成功。如果每个系统都假设下游可靠,错误就会被一层层放大。
卷二把幂等当作默认要求,而不是优化项。结算、发奖、领取、支付、补偿,每一个写操作都要回答:重复执行会怎样、执行到一半崩溃会怎样、上游重试会怎样。答案通常不是一个布尔值,而是一个状态机加一个幂等键。
问题三:哪些能力应该收进平台
三款产品共用 northstar-platform,但“共用”不等于“所有东西都放平台”。账号、支付、合规适合收进平台,因为复用度高、合规要求强、故障影响面大;匹配、战斗、经济策略通常应该留在游戏侧,因为它们变化快、与玩法强耦合。
收错的代价是双向的:平台收得太多,每次改玩法都要平台发版;平台收得太少,每个游戏重复实现一遍账号和支付,事故各修各的。卷二的第 12 章会给出一组判据,并用契约矩阵把三款产品的差异摆出来。
三款产品的系统差异
同样的系统,在三款产品里的权重完全不同。
| 系统 | 《裂隙战场》 | 《群岛纪元》 | 《泡泡工坊》 |
|---|---|---|---|
| 账号 | 自有账号 + 渠道绑定 | 强依赖渠道账号 | 游客 + 平台账号 |
| 登录 | 短票据、快速重连 | 长会话、跨区切换 | 轻量、可长轮询 |
| 匹配 | 核心体验,严格分段 | 联盟/战区为主 | 快速开局,宽松 |
| 房间 | 一局一房间,生命周期短 | 地图分片长期存在 | 房间是内部模块 |
| 结算 | 实时战斗结算,强一致 | 异步战报,可补算 | 轻量对局结算 |
| 经济 | 外观与赛季奖励为主 | 资源产出与消耗复杂 | 广告与内购混合 |
| 社交 | 好友与战队 | 联盟是核心系统 | 弱社交 |
| 榜单 | 赛季段位 | 王战与联盟榜 | 好友榜 |
| 支付 | 外观付费 | 资源礼包 | 广告 + 小额内购 |
这张表不是要证明“某款产品更复杂”,而是要说明:同一个系统在不同品类里,契约的强度不同。 竞技的结算必须实时且可回放,SLG 的结算可以异步但必须可补算,休闲的结算可以简单但不能阻塞登录。卷二会反复回到这张表,检查每个结论是否对三款产品都成立。
本卷的结构
卷二共 13 章,按“接入 → 对局 → 经济与成长 → 社交与运营 → 平台 → 收口”组织。
| 组 | 章节 | 主题 |
|---|---|---|
| 接入与身份 | 1–2 | 账号、第三方登录、登录态、网关归属、开服洪峰 |
| 对局与战斗 | 3–5 | 匹配、房间生命周期、实例分配、场景与世界、战斗与结算 |
| 经济与成长 | 6–7 | 货币账本、交易托管、经济风控、属性成长、任务与重置 |
| 社交与运营 | 8–10 | 关系链、公会、聊天、排行榜、邮件与奖励 |
| 支付与平台 | 11–12 | 支付发货、退款对账、合规、平台能力与租户隔离 |
| 收口 | 13 | 契约矩阵、数据所有权总表、进入卷三的检查点 |
每一节仍然遵循卷一的写法:先给场景与约束,再列备选方案与代价,然后给出选定方案、契约与失败模式,最后落到一个可运行的 Go 片段或一张可检查的表。
本书的四个立场
立场一:契约先于实现
接口长什么样、谁是权威、失败返回什么、重试是否安全,这些问题应该在写第一行代码之前回答。卷二里的每个系统都会先给契约,再给实现片段。实现可以换语言、换框架,契约不能靠口头约定。
立场二:幂等是默认值
任何会改变状态的写操作,都要能安全地重复执行。不是“重要接口才做幂等”,而是“没有幂等键的写接口不允许上线”。这条规则听起来苛刻,但它能把大部分重复发奖、重复扣款、重复补偿挡在事故之前。
立场三:所有权比接口更重要
接口可以有很多个,数据只能有一个写入者。卷二会反复检查:这个字段谁可以写、那个状态谁可以改。接口设计得再漂亮,如果两个服务都能写同一份数据,边界就是假的。
立场四:失败模式要写进交付物
每个系统的交付物不只是一张表或一段代码,还包括它的失败模式清单:超时、重复、乱序、部分成功、下游不可用、数据不一致。没有失败模式设计的系统,只能在演示环境里工作。
关于代码、数字与环境
卷二延续卷一的约定:代码以 Go 1.26.0 为基线,放在 gsarch-lab,每节至少一个可运行的 L1 片段;涉及外部依赖的部分标注 L2/L3,未实际运行的环境不声称跑过。
书中的在线数、延迟、成本、渠道费率都是示例值,用来说明数量级与取舍关系。标注“实测”的数字必须能追溯到命令、环境和输出。卷二涉及支付与合规,但不接真实渠道、不写真实商户号与密钥;渠道行为以接口桩和状态机表示。
最后仍然是一句老话:架构文档的价值,不在于它画得多完整,而在于它能不能让两个团队在出故障之前,对“谁负责、失败怎么办”给出同一个答案。
阅读入口:《游戏服务端架构·核心系统与契约》目录与学习路径 。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。