凌晨三点十七分。
开发部的灯全亮着,那种惨白的光从天花板上打下来,把每个人的脸色都照得发灰。
三排长条桌拼成一张大工作台,桌面上堆着十几只外卖盒,一次性筷子横七竖八地插在吃剩的米饭里,饭粒干透了,黏在塑料盒壁上抠都抠不下来。
桌上还有几罐没喝完的可乐,罐身上凝着水珠,顺着铝皮往下淌,在桌面留下一圈一圈的水渍。
桌面中间那台主机的风扇转得最响,持续不断的嗡鸣声盖过了其他所有机器的动静。
电源指示灯是蓝的,但在高速运转的时候灯芯微微发颤,像是里面的电流也在跟着喘。
李轩坐在主控机前面,上半身往前倾,两只手肘撑在桌面上,手指搭着键盘,姿势维持了快两个小时没变过。
他眼皮底下挂着两圈青,颜色很深,像是用指腹沾了灰揉上去的。
屏幕上的服务器端状态日志还在滚动,绿色字符一行一行往上冒,速度不快不慢,看着特别规律。
他盯着屏幕,眼球跟着字符移动,嘴唇微微张开一条缝,呼吸很浅,整个人的状态像一台待机的机器,盯着盯着,手指终于动了一下,按了个键。
日志停了。
最后一行字停在“连接池溢出,请求队列长度超过阈值,系统强制关闭新连接”。
他盯着那行字,大概看了有十秒,眼珠都没动。
然后他伸手端起桌角那只茶杯,杯壁早就凉透了,他喝了一口,凉掉的茶水顺着喉咙往下走,他咽下去的时候喉结动了一下。
放杯子的时候他的手重了些,杯底磕在桌面上,“咚”一声闷响,听着跟敲在木板上似的。
坐他对面的那个男生抬起头来,他怀里一直抱着个黑包,包带子绕在手腕上缠了两圈,不知道的还以为里头装着什么贵重东西,其实就是他平时背的电脑包。
他鼻梁上架着一副无框眼镜,镜片上有干掉的油渍,大概是谁吃外卖的时候溅上去的,他也没擦。
他抬头的时候眼镜往下滑了一点,他往上推了推镜架,看着李轩:“又崩了?”
“崩了。”李轩的声音很平,尾音往下坠,听着就跟在说今天吃的是盖饭一样,没什么情绪起伏,“并发数上了两千三,连接池就扛不住了。
日志显示握手阶段信号重发次数太多,超时之后大量连接卡在等待态,后面的请求全被堵在外面进不来。”
“两千三?”抱黑包的男生皱了皱眉,“昨天我们跑到两千一的时候还稳着呢。”
“是稳着。
但今天就崩了。”李轩说这话的时候伸手揉了揉后颈,脖子发出一声轻微的咔嗒响,“昨天改的是接收缓冲区的大小,扩了两倍。
但问题不在缓冲区上,握手阶段的确认机制才是瓶颈。
你接收再大的包,握手握不上来,一样白搭。”
隔壁桌的短发女生凑过来半个身子。
她坐在角落的位置,显示器屏幕的光映在她的瞳孔里,两个亮点在眼珠正中间亮着。
她手里捏着一支笔,笔帽被她咬得全是牙印。
“昨天改接收缓冲区的时候我就说了,那玩意儿治标不治本,握手协议那块的逻辑才是根子上的毛病。
我当时看了代码,握手确认那边有一个等待窗口,窗口时长设的是固定的,网络稍微波动一下窗口一卡,整个连接就拖死在那儿了。”
李轩没接话。
他把键盘往前推了推,整个人往后靠进椅背里,椅子发出“嘎吱”一声响。
他闭上眼,两只手交叉搭在肚子上。
他的眼球在眼皮底下快速地动着,左边动两下,右边动两下,频率特别快,像是在脑子里把代码从头到尾跑了一遍。
办公室里其他几个人都没出声,风扇嗡嗡转着,挂钟的秒针一下一下往前走,“嗒、嗒、嗒”,声音不大,但在安静的环境里听得清清楚楚。
然后李轩睁开眼,坐直身体,把键盘拉回面前,噼里啪啦地开始翻代码。
他的手指在键盘上敲得很快,光标在屏幕上跳来跳去,一行一行的逻辑结构在他眼前过。
他一边翻一边小声念叨着什么,声音含在嘴里,听不太清楚,像自言自语。
办公室里的气压很低。
其他几个人也都坐着没动,有人盯着自己的屏幕发呆,有人把脑袋枕在胳膊上合着眼。
外卖盒里散发出来的味道混在一起——油的,辣的,还有米饭放久了之后那股微酸的馊味。
但没人去收拾,也没人开窗。
所有人都在等,等李轩那段代码翻出一个结果来。
梁永琪推门进来的时候,身上穿着一件灰色的薄外套,拉链拉到胸口的位置,露出里面白色的T恤领子。
她手里拎着两只白色塑料袋,袋口冒着热气,塑料袋壁上凝了一层水雾。
她把塑料袋放在靠门边的那张空桌上,袋底落下去的时候发出轻微的响动。
“买了豆浆和包子,你们轮流过来吃,别一窝蜂挤着。”她说这话的时候声音不大,但口齿清晰,每个字都送得到位。
然后她走到李轩身后,低头看着他的屏幕。
她没有出声,就那么站着,两只手插在外套口袋里,目光落在屏幕上的代码行间。
她看了一会儿,没有提问,也没有催。
她知道李轩在做什么,知道他现在脑子里正转着什么东西。
她就等着。
李轩没有回头看她,也没有去碰那袋早饭。
他的手指在键盘上敲了几下,光标在某一行代码前面停下来,那一行用红色高亮标着,是握手协议里确认信号的处理逻辑。
他把光标停在那个函数名上,开口说了句:“如果握手改成三次确认之后不做连接池预分配,改成动态申请的话,能不能解决握手阶段的阻塞问题?不提前占坑,有请求来了再分配资源,握手阶段就不会因为池子满了卡死了吧?”
他旁边坐的抱黑包的男生听了,皱了皱眉,张了张嘴想说点什么,但没说出来。
他自己也在想这个问题,一时半会儿拿不准。
梁永琪听完李轩的话,没有急着表态。
她动作很自然地拿出手机,拇指在屏幕上按了几下,把李轩刚才说的那段话精简了一下,打了一行字发给陈浩。
发送成功的提示跳出来之后她把手机屏幕朝下扣在桌面边缘,等着。
手机屏幕亮着,显示收件人那一栏写着“浩哥”,消息内容缩成一行小字,看不太清。
办公室里又安静下来。
李轩的手指悬在键盘上方没落下去,他在等反馈。
梁永琪靠在桌边,眼睛看着手机屏幕的方向。
大约过了两分钟,手机震了一下。
她翻过手机,点开短信,陈浩回过来的内容不长,就一行字,她看完之后把屏幕转向李轩。
李轩凑过去看,屏幕上写着:“动态申请会引入新的分配延迟,客户端在握手确认后等待分配的那几百毫秒里如果发来后续包,会被当作无效连接处理。
问题不在分配方式,在协议层的握手时序。”
李轩盯着这条回复看了两遍。
他眉头先是皱起来,眉心挤出一道竖纹,然后那道纹路又慢慢松开,像是脑子里有什么东西“啪”一下接通了。
他把手从键盘上抬起来,两只手搓了搓脸,搓到指腹压着眼眶的时候停了一下,指头按着眼皮,好像在让眼球缓一缓。
他放下手,问:“那他有没有说什么方案?”
梁永琪又发了一条短信过去。
这回她打的是“握手时序怎么改”。
她打字很快,拇指在屏幕上点了几下就发出去了。
回信来得比刚才快,大概只隔了一分钟,手机震了一下。
她点开,陈浩的回复只有一句话:“把客户端的第一个数据包从握手之后改到握手确认之前发,服务器收到即认为连接有效。”
李轩看完这条,整个人顿住了。
他的目光停在屏幕上的那行字上,嘴里无声地动了几个字,像是在把这句话拆开了嚼碎了往肚子里咽。
他保持那个姿势大概有五六秒,然后猛地转过身面朝主控机,手指落在键盘上噼里啪啦地敲起来。
他敲得很快,几乎没停顿,一边敲一边说:“把握手确认之前的等待窗口去掉,客户端在发第三次握手确认的时候同时带第一个数据包,服务器收到之后同时完成连接建立和数据接收。
这样握手和首包合并成一个原子操作,连接池的占用时间缩短了三分之二。
原来一个连接从握手到建立要将近一秒钟,现在压缩到三百毫秒以内。
池子里的连接转得过来,后面排队进来的就能接上了。”
他旁边的短发女生已经凑过来了,脑袋几乎要贴上他的肩膀。
她盯着屏幕上正在改的代码,眼睛眯起来。
“这样改的话,首包丢了怎么办?客户端发的确认里带了数据包,服务器那边没收到的话,整个连接怎么处理?”
“首包丢失客户端重发握手确认,整个连接重建。
丢一次重建一次,跟原来的逻辑比多了一次重传开销,但丢包率本身不高,这个代价可以接受。”李轩敲完最后几行,手指在回车键上用力按了一下,按下去的时候发出“啪”的一声。
他按了保存,然后从椅子上站起来,走到那台主机的侧面蹲下去,把侧板掀开,用手电筒照着检查了一下内存条的插接状态。
他拔下来一根,用拇指擦了擦金手指,又重新插紧。
“先跑一遍单线程测试,过了再上并发。
你们别围在这儿了,去吃早饭,包子该凉了。”
他说完这话,自己却没去拿包子。
他蹲在主机边上,仰着头看机箱里的走线,一根一根地顺着线捋过去,像是怕哪个接口松了影响测试结果。
其他几个人慢慢动了。
抱黑包的男生把怀里的包搁在桌上,走到门边的桌子前拎了一只塑料袋回来,从里面掏出一只包子咬了一口,嚼了两下,又拿起豆浆喝了一口。
豆浆已经不太烫了,温的。
短发女生也走过去拿了一只包子,靠在桌边慢慢吃,她吃得慢,一小口一小口地咬,眼睛还盯着李轩那边的屏幕。
办公室里弥漫着包子的面皮味和豆浆的豆腥气。
有人吃了几口之后打了个嗝,声音不大,闷在嘴里。
李轩检查完机箱,把侧板盖上拧好螺丝,回到主控机前面坐下。
他点开刚才保存的代码,重新编译了一遍,编译过了之后开始跑单线程测试。
屏幕上跳出来测试进度条,一格一格往前移。
梁永琪靠在门框边上,抱着胳膊看着屋里这些人。
她的视线从李轩的侧脸移到那个吃包子的男生身上,又移到短发女生身上,最后落回李轩的屏幕上。
她没出声,就那么站着。
单线程测试跑完了,通过。
李轩深吸了一口气,手指悬在键盘上方,停了两三秒,然后开始调并发测试参数。
他把并发数从两千三往上调,先调了两千五,确认跑起来没崩,又往上调到三千,还是没崩,再调三千五。
测试跑起来之后,所有人都停了手里的动作,目光往主控机的屏幕这边聚过来。
时钟一秒一秒地走,屏幕上显示并发连接数稳定在三千五上下,服务器响应时间没有明显波动,日志里没有再出现连接池溢出的报错。
【跪求礼物,免费的为爱发电也行!】