招標答疑會散場後的那個周末,雲州趕上了下半年第一場像樣的秋風。昨夜風大,樓下車棚里那排電動車的防雨簾拍打鐵架拍了一整宿。周六早上林默醒來,陽台的地磚上鋪了一層細碎的楊樹葉子,邊角還帶著夜露,捻起來是涼的。夏天就這麼過去了,沒什麼儀式感。
出租屋一室一廳,家具是房東留下的老樣式,唯一稱得上他自己的東西,是書桌上方那盞暖黃燈泡。燈是他挑的,瓦數不高,亮度正好只照亮桌面那一圈。在這張桌上熬了半年多,他已經把朝向調得很熟:顯示器正對著牆,左側留出鍵盤和茶杯的位置,右側塞一塊滑鼠墊,墊子邊緣卷了角,壓著一支沒用完的原子筆。外接硬碟接著主機,指示燈在昏暗裡一明一滅,節奏很穩。
他坐下第一件事是把這幾天積攢的東西理出來。手機連上電腦,導出一沓行業群截圖,按日期命名歸檔——包括趙總監半年前在某政企交流群里那句「這次我們走的可是總部直通車「,當時群里沒人接茬,三分鐘後話題滑到了中午吃什麼。他截了,理由說不上來,只是多年運維養成的手感:先收著,反正不占地兒。
其次是從招標PDF里標黃的七處彈性條款。他重新過了一遍原文,逐條把頁碼、行號、上下文各摘兩行,謄成一張對照表,編號一到七。第三份材料最厚——銳科近三年公開渠道可查的中標記錄,一共十一個項目,每一個都附了公示連結和金額區間。三樣東西打包,全部推進給天樞。
「跑一場長推演。「他說,「把這家公司接下來能對我出的牌,儘量窮盡。推演資源今晚不設限——平時掐著用,今天反正是周末。「指令遞出去,硬碟的指示燈閃得密了起來。
他沒有盯著進度發呆的習慣。轉身去廚房燒了一壺水,把早上那杯徹底涼透的濃茶倒了,涮乾淨杯子扣在瀝水架上;再回來的時候,順手把冰箱頂上積的灰抹了一把。這些都是等推演時該乾的雜事,手上有活兒,腦子反而松。
松完了,他抽出一張A4紙,趴在桌上開始畫模塊草圖。三大塊怎麼拆,接口走哪條線,數據流向哪去——鉛筆一道一道往下寫,寫到一半,後頸那陣熟悉的震顫穩定下來,推演收斂了。
左耳後上方那段結論順著共振推送到意識前端。【四類牌。】天樞的聲音不高,語氣是念報表式的平,【資質口徑上做文章,往「相匹配「這種軟處捅;托關係壓評分,走場外的路子;比武現場跟你拼硬體參數,真刀真槍;中標之後在覆核驗收環節慢慢挑刺,鈍刀磨人。單打組合都有可能,但概率分布並不均勻。】
林默捏著鉛筆等下文。【占比最高的是三加二的組合拳——參數上正面贏你,評分面上再壓一手。這個人要的不是贏,是要當眾贏給你看。答疑會上他說「小公司理解不了也很正常「的時候,下巴抬了至少十度,眼角那個角度你自己記得。享受居高臨下的人,不屑於躲在暗處收錢,他要全場鼓掌。】
林默點點頭,鉛筆尖在紙上頓出一個黑點。這個判斷和他自己的觀察對上了。但有一層天樞沒提,他補了一句:「採購科那句「評標尺度要嚴「,你怎麼歸?「
【歸入二類的輔助動作。】天樞答得不快,像是也在掂量,【也可能是三類的配套——先嚇唬,讓你臨場縮手,縮了手,參數對拼時就少一分底氣。】
「也就是說,牌未必只打一張。「【對。所以防禦不能做成單點的。】
「嗯。「林默把草圖翻過來,在背面寫下三個詞:參數、口徑、關係。每個詞後面畫一條橫線,「那就把架子搭成這樣——他哪個方向出手,都占不到便宜。參數我跟他拼技術,口徑我提前焊死解釋空間,關係那一手,壓不動一家把活兒全做紮實的乙方。他要在檯面上拼,我就讓他拼個痛快。「
空房間裡這句話落下去,沒人反駁。冰箱壓縮機這時啟動了,嗡的一聲,響了幾秒又歸於平靜。
動手的第一步,換底座。招標文件的技術要求里夾著一整節信創目錄清單,這是明面上的硬門檻。多數乙方的做法是遷移階段再來「適配「——先順著熟悉的進口棧把系統寫通,回頭再一件一件換國產件,改到哪兒算哪兒。這個流程有個致命弱點:適配永遠排在交付壓力之後,最後多半演變成草草打補丁。林默反著來。國產分布式資料庫和國產中間件,從第一行代碼起就是底座本身,不存在二次替換這個環節。
麻煩當然有,而且都是些不起眼的小坑。國產庫的分頁語法跟舊棧差了半個方言層級,第一條SQL跑過去就報錯,錯誤碼指向的行列和實際問題隔了三層。隱式類型轉換更陰險,幾個欄位靜默降精度,聚合數字歪了一點二個百分點,他不排查要對半天報表才察覺苗頭不對。中間件那邊,連接池的心跳默認間隔跟老版本不一樣,服務掛了一個連接卻遲遲不報,假死拖到半小時後才集中爆發,日誌里一段空白像被人用橡皮擦過。
這些坑他都踩了一遍,踩過的每一個都在代碼旁邊寫了注釋,註明現象、原因和規避寫法。將來這套東西若真交出去驗收,注釋本身就是一份現成的施工說明。
底座跑通,接第二塊:彈性擴容。招標原文寫得客氣——「高峰期具備橫向擴展能力「。行內的通行解法就一個字:堆。採購清單上列十台八台伺服器,價格帶進去一算,擴容成本漂亮地撐起整個報價大頭。至於真到了業務峰值的日常態,那批機器閒著吃電,沒人心疼——電費是甲方的。
林默不打算堆機器。他的思路落在調度邏輯上:請求進來先分類,熱點請求就近打給低延遲節點,冷請求直接沉進廉價存儲。重量的分層做清楚了,同樣的機器就能扛住更高的峰值——彈性不是靠添設備添出來的,是靠把輕重分明白調出來的。
第一版切片算法寫成那天晚上,他跑了本地壓測。結果不大好看。曲線上有一個奇怪的凹陷:每當負載越過某個量級,整體吞吐反而往下掉一小截,恢復,再掉。他把錄像回放了三遍才定位到病灶——冷熱邊界判定用的條件太粗,按URL前綴一刀切,而真實的訪問熱區根本不理會URL的組織結構,同一前綴底下冷熱混著住。
問題看清了,答案反而是順藤摸出來的:判定條件從靜態的前綴規則換成動態信號——他做了一個五秒滑動的窗口,實時監測QPS的變化斜率,斜率陡增的區域就地劃成熱區。改完重跑,那條曲線順了下來,凹陷消失了,吞吐順著負載爬升一路走到頂。
他在椅子上往後挪了半寸,把這兩個改動各寫了一行注釋存檔,順手把那個廢棄的前綴方案也留在原地沒刪——留著,方便日後有人問起為什麼不用更「直觀「的路子時,拿出來對比著講。
早年他也幹過類似的事。那時把一份笨重的老方案拆成了輕量切片,合伙人聽完匯報皺眉:「這玩意兒看著不夠氣派。「一句話否了。如今這事沒人否他,他只按對錯寫字。
第三塊,雙活容災。按傳統路數,同城雙活等於再建一個機房,選址勘探專線樣樣是大開銷。林默把這條路跳了過去——政務雲本身早已鋪開了若干異地節點,他要做的只是在現有基礎設施之上搭一層邏輯雙活:數據異步雙寫,探活心跳,主節點一旦失聯,流量在極短時間內切到備端。
這一步他做得格外仔細。先把那幾個異地節點的SLA文檔找出來,一行一行核過去——端到端往返延遲的承諾值、抖動上限、維護窗口的安排——逐項確認在承受範圍以內,才敢把「邏輯雙活「四個字寫死進方案。道理不複雜:假如這一環偷懶沒查透,真出了事故就是兩頭都不認帳的局面,鍋砸在自己手裡。
模擬演練在深夜跑了一次。他在本地腳本里人為掐斷主節點,觀察備端接管的全過程。計時器停在八十四毫秒上,切換完成的提示符彈出來,全程沒有丟一條會話。他把這組數字截圖存了,標註時間,然後關掉演示進程。
最後一塊,是整套架構里他最得意的地方。那條埋在招標附件里的「安全能力與等保要求相匹配「,銳科的刀柄。三個字的伸縮全憑評標桌上一句話,今天說你匹配,明天一樣可以說你不匹配——除非,這三個字被人提前釘死成一個不可挪動的死數。
他寫了一個合規自檢模塊。等保2.0的條款被他拆出來分解成一百二十八條可勾選的硬指標,從身份鑑別粒度到日誌留存時限,一項一項落到欄位。這套模塊的使用方法極其樸素:把任何一段招標文本餵進去,它自動比對每一條硬指標,達標的亮綠,差一口氣的標黃,表述模糊無法判定的直接標紅,末尾附一份建議清單。
跑通的第一次測試,他餵的就是那份招標文件。屏幕上跳出比對結果的瞬間,第七條附件三那一行被人紅得醒目:
【模糊表述】「相匹配「——無量化邊界。建議補充:響應時限數值/覆蓋範圍清單/處置時效單位。
他伸手抓過來擱在手邊的一個文件夾,把這頁自檢報告列印出來——家裡那台老噴墨打出來的東西墨色偏淺,邊距也不齊,但內容扎紮實實。回形針別在首頁右上角,文件夾封面他寫了五個字:應對件·其一。
至此四塊齊活。三塊主功能加一個自檢模塊,總體規格高出招標要求一截,全是巧勁,沒有一處炫技堆料。
天樞從頭看到尾,這一晚上的話說得不多,多數時候只是保持一種輕微的低頻陪伴。直到最後一行注釋落定,那陣震顫才明顯活躍了一下,帶著一點罕見的熱乎勁兒:【老實說,這些東西讓人遞刀遞出來,可惜了。你這份活兒的量級,配Lv1是屈才。】
林默指尖在桌沿輕敲了兩下。他聽懂了潛台詞,也沒迴避:「Lv2的事,你我心裡都記著數呢。先用現在這套。什麼時候解,你說了不算,我說了也算不上——時機說了才算。「
【你這態度倒是一以貫之。】
「一貫的代價我有數。「他笑笑,開始收拾桌面。工程的存放位置早就想好了:不在公司任何一台伺服器,就在這塊外接硬碟的一個獨立分區里。分區的卷標是六個沒有意義的字母——他自己念過一遍就知道意思的那串,連寫下來都嫌多餘。關鍵包他又另生了一份哈希校驗值,抄在一個巴掌大的牛皮紙本上,本子和U盤一起鎖進書桌右側第二個抽屜,鑰匙拔下來揣進門邊的褲子口袋。
兩份介質,兩間屋子,互相獨立。這條規矩執行大半年,已不需靠意志力維持。
周一早上九點過幾分,陳志遠辦公室的門從裡面輕輕帶上。林默在坐下來之前快速掃了一眼這間屋子:老闆椅的皮扶手被磨得發亮,靠窗那面牆貼著大半年的項目進度板,紅黃綠三種顏色的便利貼糊得滿滿當當,有幾張邊角翹起來了,一直沒人揭。桌上立著那個熟悉的相框,嫂子和侄女的照片。窗外的梧桐葉子風一陣一陣翻卷,走廊盡頭中央空調的低頻嗡聲隔著門縫滲進來,襯得屋裡格外安靜。
陳志遠今天臉上沒多少笑。「默子,坐。「他自己先坐下了,雙手攤在膝蓋上,「我昨晚琢磨了半宿沒睡踏實。上次資質那事,咱們算是接住了。可我這心裡始終不落地——銳科那種體量,背後是什麼人,咱不知道。就怕這一來一回,把不該得罪的人得罪透了。「
林默沒急著開口。他知道這位老闆此刻真正懸在心上的,不是抽象的「得罪「二字。上次喝茶,陳志遠掰著手指頭給他算過一筆帳:廠里二三十口人,社保月繳雷打不動;財務那邊幾位親戚盯得緊;對了,還有一筆今年的個人所得稅彙算清繳,專管員上周打過電話來問情況。這些瑣碎的日子項,撐著一個老闆夜裡兩點還在床上翻身。
「銳科在幾個行業群同時放風、能把「相匹配「這樣的口子預先埋進招標文書,這樣的公司在地方上不止一家。你說他們上面有人我不懷疑,可我更知道一件事——他們真正動不了的對手,從來不是關係網上的誰,而是讓這張網根本沒法纏住的乙方。「
「你的意思是——「「我的意思是手裡這點東西。「林默說,「不是為了把人家往死角里逼。您想,真把他們摁死了,換來的是一批惱羞成怒的人挖空心思尋咱們的漏洞——那才是沒完沒了的糾纏。我要的是另一頭:讓他們親手掂掂,發現這一仗沒便宜可撿,還不如把手收回去,回去踏實做自己該做的項目。大家都有台階下,才是真正的太平。「
陳志遠琢磨了一會兒,眉頭還是有點疙瘩:「可萬一他們不認這個台階呢?「「那也得看人想不想伸手。「林默笑了笑,「我留過門,可是門的開合尺寸咱們定。「
這話含蓄,卻句句實在——那套咬合成環的架構里,他確實專門留下了兩道看起來「能鑽「的縫隙。若對面識相,那些縫隙足夠體面收兵;若對面非要鑽,那兩條預留通道在任意時刻都能在十幾分鐘內收緊成絆腳坎。什麼尺寸開多大,遙控器在他手裡,不在桌上。這一記城府不響,沒有一句硬話,卻比當面抽誰耳光都讓對方進退失據——門的開合尺寸攥在他手裡,旁人看不破,當事人心裡有數。
陳志遠盯著他的臉看了幾秒鐘,忽然嘆口氣,眼神里的東西慢慢卸掉了:「行吧。默子你這想法比我周全。我不懂技術,可我知道什麼叫讓人放心。你放手弄,公司這邊……需要什麼儘管提。「
從門口走出去的時候,林默聽見身後傳來一聲長長的呼氣。天樞在他的意識邊緣懶洋洋冒了一句:【他那顆心啊,一直吊在你昨晚往硬碟里寫東西那一刻。】
「聽到了就行。「林默把腳步放慢了半格,沒接這話。
有些帳沒必要當面算清楚。老闆的顧慮是真顧慮,不是矯情——一個扛著幾十口人飯碗的人,凡事求穩,是這個位置上唯一的合理姿勢。他的方案只能儘量做到讓對方看見風險看不見破綻,同時讓自家人感覺不到火藥味。
他回到工位,屏幕右下角的日期提醒跳了一下:距離比武正式開賽,還有九天。周二早上八點四十七分,技術比武的正式通知準時撞進陳志遠的郵箱。
那天林默正在地鐵二號線的換乘通道里走著,手機在口袋裡震了兩下。等上了扶梯,他掏出來一看,陳志遠轉發過來的原話只有一行字,末尾跟著一個豎起的拇指:「默子,你看這通知。周五。「
到了工位他才騰出手點開附件。通知寫得簡練:本周五上午九時正式開賽,採用現場環境部署方案答辯與盲測壓測相結合的方式,及格方獲准進入下一階段的邀標候選名單。附頁里最重要的信息是權重分配:盲測壓測占百分之四十,方案完整性占百分之三十,臨場答辯占百分之三十。
林默的目光在「壓測四十%「那一欄停了一秒,然後移開了。這不難猜。銳科歷年參加同類賽事的戰績擺在那裡——去年秋天市里辦的那次物流平台比武,據說現場借了二十台雲端虛機沖峰值,台上掌聲雷動,三個月後那套系統的常態支撐成了笑柄。這類手法他見過太多回了:臨時湊起來的炮仗,響一聲,煙散了。
而這,恰好是他的方案早就繞開的戰場。彈性不靠堆機器,靠分層的調度——對面越是在這塊使足力氣,越是把他自己所有的招式路徑暴露得清清楚楚。
下班回家的地鐵上,他繼續翻細則的其餘部分,順便在心裡給今晚要收尾的工作排好了順序。夜裡十點多,出租屋的書桌又一次亮起了暖黃的光。
今晚的任務不是新增功能,而是咬合。三大塊的接口此前各自通了電,彼此之間的信息流卻還沒串成一條完整的迴路。他從底座的初始化腳本起手,逐一檢查調度切片的結果如何餵給雙活的流量編排模塊,雙活的健康探針信號又要怎樣反向回流給合規自檢,充當實時校驗的數據來源。
接口定義改過兩輪。第一輪圖省事用了全局廣播,上規模卻埋了消息風暴的隱患。第二輪重構成定向訂閱:誰關心什麼就登記什麼,只收屬於自己的那一路信號,互不打擾。改完之後,整條鏈路的日誌一下子清爽了。
十一點四十,聯測啟動。他在本地模擬器中注入了一波陡增的偽業務負載——五個不同物理位置的虛擬客戶端交替拉高請求密度。面板上,三條監控曲線依次活動起來:切片路由在最前面抖了一下,隨即鎖定分流方案,命中率穩到百分之九十六點七;緊接著,雙活模塊的一次例行探活被切斷主端,備用節點接過流量的全過程報時八十一毫秒;鏈條最末端,合規自檢模塊在做完本輪全量掃描後彈出結論行——本輪校驗:128項,通過128,異常0。
以及一條被他刻意放在最後的暗註:預留檢修口·通道A·當前狀態開放;通道B·當前狀態開放。這兩行字眼掃過去,他停了幾秒鐘,然後在終端里輸入一行指令,把通道B的可探測閾值下調了零點五檔——不影響正常運行,只在外部有針對性探測時會呈現「恰像一個可以鑽的洞「的樣子。什麼時候封,封到什麼程度,等對面伸手的那一刻再決定。
保存。退出。合蓋。
筆記本合上的一瞬,暖氣片管道深處傳來輕微的一聲水響,大概是樓上哪家夜裡調節了閥門。窗外的梧桐枝影投在窗簾布上,被路燈映出一層淡淡的輪廓,風過了,才慢慢靜止下來。
他把外接硬碟從主機上拔下來,握在手裡掂了掂,走到書架前蹲下去。第三格里繞著的那捆舊數據線還是老樣子,一點沒挪窩。他把硬碟側著身子塞進線圈最裡頭的縫隙,用其中一根電源線隨便一繞,外觀上瞧就跟雜物混在一塊兒了。做完這一切,他用鉛筆在便簽紙背面隨手寫了個只有自己認識的代號,撕下來貼在硬碟外殼邊緣——不寫內容,只做標記。
起身的時候膝蓋咔了一聲。書架上那一層還並排躺著他常用的幾本書,一本藍色封皮的《故障排除手冊》斜靠著箱體立著,是入職第一年買的,邊角都卷了。他的視線從書上掠過,突然想起還有一件事沒做:明天別忘了給老周的閨女那瓶汽水的承諾續上說個准日子——周哥嘴上不說,指不定心裡還惦記著那句玩笑話。
燈滅了。窗簾縫裡透進來的城市微光在地面上薄薄攤了一片。隔壁樓的某一扇窗戶里,鋼琴聲斷斷續續飄上來,彈琴的人在反覆練習同一個樂句,錯了,重來,又錯了,又重來。
九天。
林默躺在黑暗裡,呼吸慢慢勻下去。他想到周五那間布置好的賽場,想到評委席後面那幾張還沒見過面的面孔,想到對面那把漂亮的西裝口袋裡也許正別著一疊印滿漂亮數字的PPT——想到這裡,他的嘴角牽了一下,很快就睡著了。
明天的巡檢日程還壓在手機備忘錄里,得早些起來,一件一件照舊做完。可九天後的那間賽場,真正的懸念在於——對面西裝口袋裡那疊印滿漂亮數字的PPT,到底能不能像他們想的那樣響。他閉著眼,把答案留給了九天後的自己……