内存爆灯
最近产品在韩国上线了,上线后的第一个周末,人数最多的一服内存爆了,被 OOM 杀掉宕机了,很郁闷
机器用的 4 核 16G,aws 的实例。周四开服后,每天零点左右的在线人数峰值,内存都超过了 80% 的告警线。但是运营方不希望停机,于是采取了定时通过 GM 指令调用 gc,15 分钟回收一次内存,希望撑过峰值。到了周六晚,白天加班回到家,有点松懈了,就没再盯着内存曲线看,结果一不留神就爆了。。。峰值从 78% 飙升到 91%,只用了 7 分钟,定时 gc 没赶上,就这样挂了
按之前内网的压测结果,支撑 3300 人同时在线是没问题的。现在回头看,这个性能指标没有考虑到玩家获得大量武将、装备的情况。初级玩家 3300 人是没问题的,但是上升到一定级别的玩家,就不好说了。国服上线没有问题,是因为国服求稳,开服前先将内存升到 32G,一周后再降配,外服直接上 16G,是有点大意了。
另一个是代码的问题。之前有几个服务用于缓存角色数据,避免重复从数据库里存取。后来分析了一下,这个缓存实在没什么用,玩家角色基本只会上线时自己读一次,以后写数据也是直写到数据库里的。还有一个比较意外的,是有个服务需要读玩家的基本角色信息,以及封禁信息。但是,当时写的同事大意了,直接将整个玩家数据查了出来,还缓存在服务里了。这两块优化了以后,实测内存降了几 G
然后是 GC 的问题。Lua 5.3 取消了分代 GC,要等 lua vm 遍历完所有对象后,才开始释放。当对象的数量特别多的时候,gc 就需要比较长的时间来 mark 完。另外,Lua 的 GC 感觉比较惰性,看了下 lvm.c 的代码,在新建 table、concat 一个 table、创建一个闭包的时候,才会跑一个 step。至于跑多少个 step 可以完成一次完整的 gc 呢?不确定然后有两个服务,占用内存比较多,也没有显式的调 gc,所以回收比较慢。
除了 GC,按 Skynet 社区的经验贴 ,jemalloc 的参数也可以调优下,增加后台进程,积极回收没使用的内存。同时,释放的内存和分配后剩余的内存,都改成立即回收。