site logo

Marico's space

可扩展的寻宝游戏是个神话,但我们差点就实现了

前端技术 2026-05-28 20:55:30 3

最近折腾了一个寻宝游戏的后端系统,踩了不少坑,这篇把问题说清楚。

我们实际上在解决什么问题

回过头来看,我们其实并没有真正解决服务器基础设施的扩展问题,而是在解决内部架构的问题。团队设计的系统是模块化的,各个组件通过复杂的消息队列和 HTTP(超文本传输协议)请求网络相互通信。我们试图将微服务架构模式应用到一个非常具体的问题上,但最终效果并不如预期。越想扩展,性能指标就越差。我们观察到平均 95 百分位延迟攀升到了 400ms,Web 服务器的 CPU 利用率开始触及 80% 的天花板。

我们最先尝试了什么(以及为什么失败了)

第一反应是优化服务器上的数据库查询。我们知道数据库是个严重的瓶颈,所以开始调整查询计划、索引和缓存策略。甚至重写了一些查询语句,但这并没有真正起到作用。延迟开始下降,但只是几毫秒,CPU 利用率仍在持续上升。显然数据库只是冰山一角,真正的问题深埋在系统内部。

架构决策

于是我们退后一步,重新评估架构设计。意识到模块化系统实际上是性能的阻碍,而不是助力。组件间的通信产生了不必要的开销,系统开始变得像一个分布式单体。我们决定采用不同的方案——选择单线程的内存缓存来存储游戏状态,然后用消息队列异步处理更新。这个设计简单得多,但事实证明这是解决性能问题的关键。

改动之后的数字

实施新设计后,性能有了巨大提升。平均 95 百分位延迟降到了 50ms,Web 服务器的 CPU 利用率降到了 30%。我们能够轻松处理数千并发用户,系统响应也变得更加灵敏。内存分配次数也显著下降,这曾是我们的一个痛点。应用不再持续消耗 CPU 和内存,我们还删掉了一堆不必要的缓存和队列代码。

如果重来会怎么做

事后看来,应该从一开始就采取更激进的系统设计方法。我们试图用模块化系统造轮子,实际上更简单的设计会更有效。也会在开发周期中更早关注性能测试,而不是等到最后关头。最后,对于编程语言和运行时的选择应该更加谨慎。我们选用了 Python,虽然是门好语言,但对于需要高并发的系统来说并不是最佳选择。我们不断与内存安全问题和性能瓶颈作斗争,让工作变得比预期的要艰难得多。

原文链接:https://dev.to/...