最近产品在韩国上线了,上线后的第一个周末,人数最多的一服内存爆了,被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的参数也可以调优下,增加后台进程,积极回收没使用的内存。同时,释放的内存和分配后剩余的内存,都改成立即回收。