背景:架构问题通常藏在正常路径之外
游戏里的通知远不止一条消息。背包满了要提示,好友上线要提示,活动快结束要提示,赛季结算要提示,支付到账要提示,系统维护要提示。它们如果都走同一条实时推送链路,玩家会被弹窗淹没,关键消息也可能被低价值红点挤掉。通知优先级投递架构的目标,是让不同价值、不同时效、不同打扰程度的通知走适合自己的路。
很多项目把通知系统做成一个 sendMessage 接口,调用方传玩家 ID 和文本。短期足够,后期会出现三类问题:一是重复通知,多个系统都告诉玩家同一件事;二是时机错误,战斗中弹商城活动;三是不可追踪,玩家说没收到奖励提示,服务端只知道发送过,不知道客户端是否展示过。
通知应拆成事件层、聚合层、优先级队列、投递适配层和到达回执。业务系统只上报通知意图,聚合层负责合并和去重,队列按优先级和场景选择投递时机,客户端回报展示和点击结果。
架构视图
flowchart TD
E[业务通知意图] --> A[聚合与去重]
A --> P{优先级与场景}
P -->|强实时| R[实时通道]
P -->|可延迟| Q[延迟队列]
P -->|摘要| S[红点/摘要模型]
R --> C[客户端展示]
Q --> C
S --> C
C --> ACK[展示/点击回执]
这张图只展示主干流程,实际落地时还要补上权限、审计、监控、配置版本和异常补偿。画架构图的意义不是让系统显得复杂,而是让团队在写代码前确认几个问题:状态在哪里被创建,在哪里被修改,失败后谁负责收尾,玩家能看到什么结果,客服和研发能不能在事后还原过程。
设计要点 1
通知优先级不能只靠调用方自觉。建议定义系统级别:P0 强制提示,例如维护、封禁、支付异常;P1 重要业务,例如奖励到账、组队邀请;P2 可延迟提醒,例如活动快结束;P3 摘要型红点,例如图鉴更新。不同级别有不同打扰规则和限流策略。
设计要点 2
场景感知很关键。玩家在实时战斗中,不应该被普通活动弹窗打断;玩家在结算页,奖励提示可以合并展示;玩家离线时,部分通知进入离线摘要,部分可以推送到系统推送。通知服务需要知道玩家当前 scene 或 mode,至少由客户端和网关上报粗粒度状态。
设计要点 3
聚合能减少噪声。十个任务进度变化不需要十个弹窗,可以合并成“有 3 个任务可领取”;好友连续上线可以折叠;活动提醒可以按活动维度保留最后一次。聚合规则应配置化,但服务端要有硬限制,避免运营配置把玩家体验打爆。
设计要点 4
到达回执要区分送达、展示、点击。服务端发送到网关只说明链路成功,客户端展示才说明玩家看见,点击才说明产生行为。不同通知的关键指标不同,维护公告看展示率,活动提醒看点击率,奖励到账看投诉率和补看率。
设计要点 5
通知存储要有生命周期。强通知和资产相关通知需要较长保留,可延迟提醒过期后应自动清理,红点摘要可以只保留当前状态。没有生命周期的通知表会在长线运营中不断膨胀。
数据模型与状态边界
这类模块不要只围绕一张数据库表设计。更稳妥的方式是先定义领域对象、命令、事件和读模型。领域对象负责维护权威状态,命令表达一次业务意图,事件记录已经发生的事实,读模型服务客户端展示和运营查询。这样做会比直接增删改查多一些代码,但当系统进入长线运营后,状态边界会清楚得多。
每一次关键状态变化都应该带上版本号和来源。版本号用于并发控制和缓存失效,来源用于审计和问题定位。比如一次来自活动配置的变更、一次来自玩家操作的变更、一次来自补偿脚本的变更,处理策略可能完全不同。没有来源字段,线上排查时只能翻调用链猜测。
状态边界还决定了能否拆服务。如果一个模块必须同时读写十几个系统的内部表,它后面很难独立扩容,也很难做灰度。相反,如果它只暴露命令接口和事件输出,其他系统通过读模型或订阅事件协作,拆分和回滚都会简单很多。
失败路径与补偿策略
游戏服务器必须把失败当成常态。玩家会断线,客户端会重试,网关会重连,数据库会超时,配置会临时回滚,外部平台会延迟回调。架构设计如果只覆盖成功路径,测试环境里看不出问题,线上高峰时会集中爆发。
建议为每个核心动作定义四类结果:成功、业务拒绝、可重试失败、不可自动处理失败。成功进入正常事件流;业务拒绝返回明确原因,例如条件不满足或状态已变化;可重试失败进入带幂等键的重试队列;不可自动处理失败进入死信或人工工单。不要把所有异常都包装成系统繁忙,否则调用方无法采取正确动作。
补偿策略要和幂等设计绑在一起。补发奖励、恢复状态、重放事件、重新生成读模型,都必须能识别之前是否已经执行过。没有幂等键的补偿脚本,是很多二次事故的来源。
性能与容量估算
性能设计要从业务峰值倒推,而不是上线后再看机器报警。先估算单玩家、单房间或单账号在高峰场景下的请求频率,再乘以同时在线和活动放大系数。很多系统平时负载很低,一到赛季结算、限时活动、主播开黑或版本更新,就会出现数倍甚至数十倍尖峰。
容量估算时要分清 CPU、内存、网络、存储和外部依赖。一个模块可能 CPU 很轻,但写放大严重;也可能数据库压力不大,但网关推送带宽很高。只看 QPS 容易误判。建议在压测脚本里模拟真实操作序列,而不是只压单个接口。
为了防止局部热点,需要准备限流、批处理、合并、异步化和降级。降级不是失败,而是提前定义较低质量但可接受的服务形态。例如延迟刷新、摘要展示、只读模式、排队等待、转邮件托底。
观测与排障
观测指标至少分三层。第一层是玩家结果,例如成功率、拒绝率、延迟分位、可见错误、投诉量。第二层是系统状态,例如队列积压、缓存命中、回源耗时、事件延迟、重试次数。第三层是证据链,例如请求 ID、玩家 ID、配置版本、策略版本、状态版本、裁决原因。
排障面板要支持按区服、玩法、客户端版本、配置版本和时间窗口切分。游戏事故很少平均发生,通常集中在某个活动、某个灰度桶、某个地图或某个玩家群体。没有这些维度,平均值会把问题掩盖。
日志不要只记录错误。对资产、结算、处罚、关系、进度这类高价值变更,成功日志同样重要。玩家争议发生时,研发需要证明系统当时做了什么,而不是只知道没有报错。
上线与回滚建议
上线时尽量先走影子模式或小流量灰度。影子模式可以让新逻辑计算结果但不影响玩家,用来观察和旧逻辑的差异;小流量灰度可以验证真实玩家行为和边界场景。直接全量切换只适合低风险展示功能,不适合影响状态和资产的核心模块。
回滚路径要提前演练。代码回滚、配置回滚、开关熔断、读模型重建、事件重放、人工补偿分别解决不同问题。一次事故中常常需要组合使用。没有演练的回滚,在真正事故时会变成新的风险。
上线后至少观察一个完整业务周期。如果是日常任务,要跨过一次日重置;如果是排行榜,要跨过一次结算;如果是副本,要覆盖断线恢复和奖励领取。只看发布后十分钟没有报错,不能说明系统可靠。
常见误区
第一,把客户端表现当成服务端事实。客户端可以预测、缓存和合并,但服务端必须有自己的权威状态和裁决理由。
第二,把平均延迟当成体验指标。游戏玩家感知的是尾部延迟、连续失败和关键动作是否被正确处理。
第三,把配置灵活性当成安全性。配置越灵活,越需要校验、灰度、版本和回滚。
第四,把重试当成补偿。没有幂等和状态检查的重试,只是在放大错误。
第五,把后台工具当成内部小功能。运营、客服、研发都会在压力下使用这些工具,权限、审计和结果反馈必须按生产系统标准设计。
工程落地细节
通知聚合层需要维护 notificationKey。比如同一个活动的倒计时提醒,不管由运营脚本触发还是活动服务触发,都应该落到同一个 key 上,后来的提醒更新前一条,而不是新增一条。资产到账类通知则不能随便合并,因为每一笔到账都可能对应客服证据。
客户端回执也要防止刷量。展示回执可以批量上报,点击回执需要带通知版本和展示时间。服务端根据回执更新通知状态,但不能把客户端回执当成资产领取事实。通知系统只证明玩家看见了提示,不证明奖励已经发放。
排障时最常见的问题是“服务端发了但玩家没看到”。这时要沿链路查:业务是否生成意图,聚合层是否合并,队列是否延迟,网关是否在线,客户端当时处于什么场景,展示规则是否压制。每一步都有状态,才能避免互相甩锅。
线上案例化复盘
某次节日活动上线后,玩家进入主城立刻收到活动弹窗、好友上线、邮件提醒、任务完成、礼包推荐五类提示。运营觉得曝光足够,玩家实际感受是界面被打断。后来团队把通知分为“必须立即展示”和“进入空闲态再展示”,并引入会话级展示预算:同一场景切换后的前 5 秒最多展示一个弹窗,其余转成红点或摘要。活动点击率没有下降,关闭率和投诉量反而明显降低。通知系统的目标不是发得越多越好,而是在合适时机让玩家看到该看的信息。
交付检查清单
通知系统交付时,不要只验“消息能发到客户端”。还要验证同一通知重复触发是否会合并,玩家在战斗中是否被普通弹窗打断,离线再上线是否能看到未过期通知,过期通知是否自动清理,展示回执是否能在后台查询。对于 P0 通知,还要演练网关断线、客户端版本过旧和玩家在副本内的情况,确认关键消息不会被低优先级队列压住。
接口契约补充
接口契约要把调用方能依赖的内容写清楚:请求字段哪些必填,幂等键如何生成,成功后状态何时可见,失败是否允许重试,客户端应该展示什么文案键。很多线上误会不是服务端没有处理,而是调用方不知道这个接口到底承诺什么。把契约写进文档和自动化用例,比口头约定可靠。
小结
游戏通知优先级投递架构的价值,不在于把所有情况都抽象成一个万能平台,而在于把高频路径、失败路径和争议路径都设计清楚。玩家看到的是一次点击、一次移动、一次领取或一次切换,服务端背后需要处理顺序、状态、版本、并发、补偿和证据。
如果团队资源有限,建议先做三件事:明确权威状态,补齐幂等和版本,建立能回答争议的日志。做到这三点,即使系统还不够优雅,也具备持续演进的基础。后续再加入灰度、自动化修复、容量模型和可视化工具,架构会自然长成,而不是被事故一次次推倒重来。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。