屏幕上是“山海”压力测试的监控面板。左侧是实时数据:在线人数 8,427,还在缓慢增长;帧率 28 FPS,勉强可玩;网络延迟 112 ,偏高但可接受。。所有指标都在危险边缘跳舞。
阿坤坐在监控台前,背挺得笔直,但手在抖。他眼镜片上反射着屏幕的光,那些跳动的数字像心电图,显示着“山海”这个新生世界的脉搏——虚弱,但还在跳。他已经四十八小时没合眼,下巴的胡茬青黑一片,眼里的血丝像蛛网。
“一万了。”王磊的声音从身后传来,很轻,但在一片死寂中像炸雷。
在线人数突破一万。这是“山海”。测试用户是浩宇从《血战天下》老玩家里招募的志愿者,两千人,加之八千个仿真机器人。服务器是刚采购的戴尔PowerEdge 2650,四路至强,16GB内存,在2004年算是顶配。
但现在,顶配服务器在呻吟。
“数据库响应时间突破500毫秒了。”张一鸣盯着另一个监控界面,声音平静,但眉头紧锁,“索引命中率在下降,有全表扫描的迹象。我们的查询优化器可能有问题。”
“关掉非内核服务。”阿坤说,声音嘶哑,“邮件系统、排行榜、聊天频道,全部停掉。集中资源保内核玩法。”
“已经在做了。”赵永在另一台机器上快速操作,“但数据库连接池满了,新请求在排队。等待队列已经积压了三千多个查询。”
“清连接。把闲置超过三十秒的连接踢掉。”
“踢了,但新连接创建需要时间,玩家会感觉卡。”
“顾不上了,先保住服务器不崩。”
玻璃房里键盘声密集起来,像暴雨敲打铁皮屋顶。每个人都在自己的终端上操作,关服务,调参数,杀进程。
凌晨一点四十七分,第一波玩家掉线。世界聊天频道(还没关掉的部分)开始刷屏:
“卡死了!”
“动不了!”
“技能放不出来!”
“服务器炸了?”
阿坤的手指在键盘上飞舞,调出数据库慢查询日志。日志在疯狂滚动,每秒新增几百条。他快速扫描,锁
“这个查询,”。全表扫描,每秒执行几千次,数据库不崩才怪。”
“谁写的?”王磊问。
“我。”陈默的声音从角落传来,很小,“物品系统我负责的。我想一次查出玩家所有类型的物品,减少查询次数……”
“想法没错,但实现错了。”阿坤快速改代码,“拆成十个查询,用UNION,或者用临时表。但现在来不及了,先加force index强制走索引。”
他改完,部署。三
凌晨两点零八分,在线人数突破一万二。服务器开始出现周期性卡顿:每三十秒,帧率掉到5以下,持续五秒,然后恢复。玩家骂得更凶了。
“是GC(垃圾回收)。”张一鸣调出JVM监控,“老年代内存满了,每次Full GC要五秒。我们的对象创建太频繁,特别是技能特效和伤害数字,每个都是独立对象,用完就丢。”
“用对象池。”阿坤说,“但现在改不了,先加大堆内存。”
“已经最大了,16G全给了Java。物理内存不够了。”
“那就砍特效。同屏技能特效超过十个,后面的不显示。”
“在做了。”
凌晨两点三十三分,在线人数一万三千五百。。这是死锁的典型特征——某个资源被竞争,线程在等待中休眠,然后被唤醒,继续竞争。
“数据库死锁。”赵永调出死锁日志,屏幕上一片红,“事务A锁了玩家表行1,等待物品表行2;事务B锁了物品表行2,等待玩家表行1。循环等待,超时后自动回滚,但新请求又来,继续死锁。”
“事务隔离级别是RR(可重复读)?”阿坤问。
“是。我们之前为了数据一致性,设的RR。”
“改成RC(读已提交)。先活下来,再谈一致性。”
“改了,需要重启数据库。”
“重启。”
数据库重启花了三分钟。这三分钟,所有玩家掉线。世界频道最后一条消息是:“浩宇牛逼,把服务器测炸了!”后面跟了一串笑哭的表情。
凌晨两点四十一分,数据库重启完成。玩家重新连接,在线人数慢慢爬回八千。但所有人都知道,测试已经失败了。万人同图的目标,在现实面前碎了一地。
玻璃房里死寂。只有服务器风扇还在响,但声音听起来象嘲讽