首页 > 网游竞技 > 代码:烬 > 第10章 海量请求

第10章 海量请求(1/1)

目录

凌晨两点整。

林劫按下回车键的那一瞬间,变压器房里所有的屏幕同时闪了一下——不是物理意义上的闪,是数据流突然爆发导致渲染引擎掉了一帧。那个画面沈易后来回忆了好几次都说不太清楚,就像一个装满水的塑料袋被人从底部戳了个洞,水不是流出来的,是炸出来的。

两百万台设备在同一微秒收到了同一个指令。指令的内容用人类语言描述起来很简单——向龙吟系统公共DNS根服务器发起域名解析请求,每台设备每秒发送八到十二次,每次请求的域名从模板库里随机抽取,请求头伪装成正常的用户查询流量,TTL值随机分布在六十到三百秒之间。简单到任何一个学过网络编程的本科生都能写出类似的脚本,但两百万台设备同时做这件事,就把“简单”变成了“灾难”。

龙吟系统公共DNS的三组根节点分布在瀛海市三个数据中心——城西的龙穹科技总部地下机房、城东的滨海数据枢纽、以及城南的备用容灾中心。正常运行时,三组节点各承担大约三分之一的查询流量,彼此之间通过两条主用光纤链路和一条备用微波链路维持数据同步,健康检查间隔是五秒。任何一台节点在五秒内如果响应延迟超过五百毫秒,负载均衡器就会自动把流量切给另外两台。这个机制在平时是合理的——很少有外部攻击能同时打穿三个互为备用的节点,更何况每个节点的峰值处理能力是每秒钟五百万次查询——三组加在一起是一千五百万次,理论上需要同时发动至少两千万台肉鸡才能勉强触及这个阈值,而瀛海市的物联网设备总数也不过三千万台出头,其中还有将近一半因为固件版本太新、厂商及时打了补丁、或者干脆没联网而无法被利用。

但林劫从一开始就没打算靠数量取胜。

他瞄准的不是节点的处理能力上限,而是负载均衡器本身的逻辑缺陷。三组节点同时过载时,健康检查模块会陷入一个设计者从未预料到的状态——两台幸存节点会同时尝试接管宕机节点的流量,但由于彼此之间无法在毫秒级协商优先级,它们会各自独立地向外广播“我可以接替”的声明。两份声明在核心路由器上产生路由表冲突,冲突持续的时间窗口极短——大概只有一到两秒——但在这个窗口里,所有发往DNS根节点的流量都会被反复在两个节点之间来回乒乓,没有任何一台服务器能真正处理这些请求。

而林劫要做的,就是在这一到两秒的窗口里,把三组节点全部拖入过载状态。

屏幕上跳出了第一批实时数据。城西节点——也就是龙穹科技总部地下机房那台——的查询请求量从基线的一百二十万次每秒瞬间跳到四百三十万,只花了四秒。四秒之后是六百八十万,再过三秒直接撞上了九百九十万。这个数值已经远远超过了单台节点的理论峰值五百万,超额部分的流量溢出到了核心路由器的输入缓冲区,缓冲区在零点三秒内被塞满,然后开始丢包。第一批丢掉的包是外部用户的普通查询请求——普通市民的手机、平板、智能家居、车载导航开始发现上网不顺畅了。第二批丢掉的包是健康检查模块自己发出的握手信号——但因为健康检查信号的优先级标记和普通用户请求完全相同,在缓冲区溢出时被同等对待地丢弃了。

城西节点没能在五秒内响应健康检查。负载均衡器毫不犹豫地启动了接管程序,把原本路由到城西节点的流量一股脑儿地切给了城东的滨海数据枢纽,同时向城西发出了“你还好吗”的二次查询包,但这个查询包同样被卡在炸裂的输入缓冲区里,根本没送到服务器面前。城东节点接到额外流量之后的四秒内,它的查询请求量从一百三十万跳到了七百九十万,比城西节点倒得更快——因为这台服务器型号偏旧,是五六年前部署的,内核网络栈没优化过,中断处理的亲和性很差,CPU在负载超过六百万时软中断响应延迟急剧恶化。

第二台节点开始丢健康检查包。第一台还在挣扎着试图恢复,第二台已经在往下倒——负载均衡器开始慌了。它把两台“可能出问题”的节点的流量全部切向城南的备用容灾中心,而备用节点本身是一台半休眠的低功耗服务器,平时只做数据同步备份,从没被配置过处理全城级别的查询请求。它的最大处理能力不是五百万,是两百万出头。在流量涌入的一瞬间,系统日志里留下了一条极短的WARNING——“超出最大并发线程数,内核OOMKiller已触发。”

OOMKiller优先杀掉了DNS解析服务进程。备用节点不是过载,是直接死了。

三台根节点,一台还在挣扎,一台半死不活,一台死透了。备用微波链路还没反应过来——切换微波链路需要大概十五秒,比光纤的接管延迟多了整整一个数量级。在这十五秒里,整个瀛海市的公共DNS服务彻底停摆。

从林劫按下回车键到这一刻,十四秒。

沈易坐在他旁边那把破折叠椅上,屏幕上是他自己负责的交通信号模拟——逻辑炸弹还没触发,但DNS解析服务的停摆已经让交通系统的部分外围模块开始自行报错了。他抬头看了一眼主城区方向的监控画面,那些还亮着的全息广告牌忽然变得迟钝,好几块同时失去响应,画面卡在半空中没人来刷新,像张褪色褪到一半就放弃了的旧照片。

“开始了。”沈易说。

“还没。”林劫盯着第二块屏幕上电网控制节点的状态,等着物理层的回应。

旧港区变电柜里,老鬼的手表秒针走到第五格时——他的手表比原子钟慢了一秒多,但没关系,电压源的晶振是按照林劫发的基准校准的,误差控制在零点零三秒以内,比他自己脉搏还准。触发脉冲到达控制回路的输入端时,老鬼正拿着螺丝刀在检查最后一根跳线的接触,脉冲直接把霍尔传感器输出端的基准电压从零点七伏拉到了一点二伏——模拟出来的过流值让过流保护模块在三毫秒内就判定出一次严重过载,立即切断主变高压侧断路器。六氟化硫灭弧室在断开的瞬间发出一声极低沉的闷响,像被人闷在水里敲了一下鼓。接着是锈带北,老鬼的徒弟阿六在那蹲了好几个小时腿早麻了,信号一来拧开那玩意儿的时候手都在抖。然后是锈带南,疤头从塑料布底下猛地坐直身子,一脚踢翻了脚边的工具箱,金属工具哗啦啦撒了一地,但他顾不上管。三组断路器在零点四秒内全部跳开,电压尖峰沿着线路往上直窜,主变保护启动,备用电源切换指令正常发出——但切不进来。

不是因为设备坏了,而是因为林劫在十四秒前已经在网络层对电网控制节点的同步信号动了手脚。备用电源切换指令被延迟了——被卡在一个不断重复的握手循环里,控制模块一直在问备用电路“准备好了吗”,备用电路一直在回答“准备好了”——但主控就是不放行。延迟时间被林劫设定为五秒,不多不少,刚好够电压尖峰到达电网分布式控制节点,又不够让ICU里的维生系统彻底断电。

五秒后,备用电源顺利切入。医院的灯闪了一下——就只是闪了一下。没人死。至少不是因为这个。

但在这五秒里,电网控制根节点失去了与下层变电站的同步信号,按照设计好的保护逻辑,它判定电网发生了大规模事故,主动将自身切入了离线保护状态。龙吟系统的三个根服务层——DNS、交通、电网——已经有两个被打断了脊椎。只剩下最后一个。

目录
返回顶部