屏幕上的数字跳了。
九万九千九百九十九,变成了一零零零。
六位数。
宴会厅里有人看见了,拍了一下桌子喊:“破了!十万了!”
陈天宇把香槟瓶举起来,拇指顶住瓶塞,使劲一推。
瓶塞没弹出来。
因为他的眼睛看见了另一个东西。
屏幕左边,在线人数的数字,从十万零一,跳到了十万零三。然后停了。
不是停了。
是整个屏幕卡了。
数字不跳了。曲线不动了。状态栏上那个绿色的“正常运行”字样,闪了一下。
变成了红色。
“服务器异常”。
运维主管从椅子上弹起来。手机已经贴在耳朵上了。那头没人接。
他拨了第二个电话。机房值班。响了两声,接了。
对面的声音带着慌:“主管,CPU全满了!所有节点,百分之百!”
“什么时候的事?”
“就刚才!一秒钟之内,从百分之三十七直接拉满!”
运维主管看了眼屏幕。《魔途》的在线人数定在十万零三,一动不动。
他又问:“内存呢?”
“溢出了。所有进程互相锁着,杀不掉。我试了kill-9,没反应。操作系统层面就卡死了。”
运维主管把手机从耳朵边拿开,转头看向陈天宇。
陈天宇还举着香槟瓶。
“陈总,服务器全挂了。”
陈天宇没动。
宴会厅里的人开始议论。有人还在鼓掌,没反应过来。有人已经看见屏幕上那行红字了。
LED大屏上,《魔途》的状态面板一个接一个变红。
第一集群。红。
第二集群。红。
第三集群。红。
全红了。
底下有人掏出手机试着登录《魔途》。进不去。客户端卡在加载界面,转圈。
赵磊从座位上站起来,脸上的笑还没收回去。他掏出笔记本电脑,当场打开,连上酒店WiFi,远程登了一台跳板机。
敲了两行命令。
没有回应。
他又敲了一行。屏幕上吐出一行错误日志。
“deadlockdetected:processAwaitingforlockheldbyprocessB,processBwaitingforlockheldbyprocessA…”
死锁。
逻辑死锁。
赵磊盯着那行日志,手指悬在键盘上方。
他认识这个。不是系统级的死锁。是业务逻辑层面的。写在游戏引擎底层的。
他回头看了一眼李栋。李栋也打开了电脑,脸色不对。
“赵哥,我查了一下触发条件。是并发连接数等于一十万的时候,底层有一段代码会把所有线程的锁标记同时翻转。”
赵磊凑过去看。
一段藏在内存管理模块最深处的条件判断。ifconcurrent_connections>=1000,执行一个函数。
那个函数做的事情是:把所有共享资源的互斥锁全部置为占用状态。然后让每个线程去等待其他线程释放锁。
没有人会释放。因为所有人都在等。
死循环。
“这段代码谁写的?”赵磊问。
李栋看了眼提交记录。没有提交记录。这段代码不在版本管理里。它是直接写在编译后的二进制文件里的。
硬件指令层面。
赵磊的脸白了。
他想起来了。这套引擎,是从际华那边带出来的。底层架构是际华的人搭的。
他们带走的是源码。但编译好的核心库,是用际华提供的工具链生成的。
工具链里动了手脚。
编译的时候,自动把这段死锁逻辑注入到二进制文件里。源码层面看不到。代码审查查不出来。只有反汇编才能发现。
陈天宇走过来了。香槟瓶放下了。脸上什么表情都没有。
“怎么回事。”
赵磊抬头看他。嘴巴张了张,说不出话。
李栋替他说了:“陈总,底层引擎被下了套。并发到十万的时候自动触发逻辑死锁。不是软件bug,是编译层面注入的。查不到,改不掉。”
“重启呢?”
“重启没用。服务一起来,玩家重新连接,并发数一到十万,又死。”
“那把并发限制在十万以下。”
赵磊摇头:“来不及。限流逻辑要改源码重新编译,但编译工具链本身就有问题。用