那個(gè)被架構(gòu)圖“毀掉”的項(xiàng)目,教會(huì)我的5件事
引子
2022年,我參與過(guò)一個(gè)失敗的項(xiàng)目。
項(xiàng)目代號(hào)“天穹”,目標(biāo)是重構(gòu)公司核心交易系統(tǒng),預(yù)算800萬(wàn),周期8個(gè)月。
結(jié)果呢?8個(gè)月后,項(xiàng)目延期,預(yù)算超支,核心成員走了三分之一。最后草草上線,半年后徹底廢棄。
復(fù)盤會(huì)上,大家找了很多原因:需求不清晰、管理混亂、技術(shù)選型失誤……
但我心里清楚,有一個(gè)原因被忽視了:我們被架構(gòu)圖騙了。
一、漂亮的圖,坑人的坑
項(xiàng)目啟動(dòng)時(shí),總架構(gòu)師畫了一套“史詩(shī)級(jí)”架構(gòu)圖。
微服務(wù)拆分16個(gè),服務(wù)網(wǎng)格、分布式事務(wù)、CQRS、事件溯源,該有的全都有。圖一展示,老板鼓掌,全員沸騰。
開發(fā)團(tuán)隊(duì)拿著圖,開始寫代碼。
第一個(gè)坑:圖是理想的,代碼是現(xiàn)實(shí)的
圖畫了16個(gè)微服務(wù),但現(xiàn)有代碼是單體。從單體拆到微服務(wù),中間要經(jīng)歷無(wú)數(shù)個(gè)“中間態(tài)”。架構(gòu)師說(shuō)“分階段實(shí)施”,但沒人說(shuō)清楚:第一階段拆哪幾個(gè)?第二階段怎么過(guò)渡?數(shù)據(jù)怎么遷?
開發(fā)按自己的理解拆,A組拆成這樣,B組拆成那樣。等聯(lián)調(diào)的時(shí)候發(fā)現(xiàn),服務(wù)之間對(duì)不上——A的訂單服務(wù)和B的支付服務(wù),數(shù)據(jù)模型不兼容。
教訓(xùn)1:架構(gòu)圖要分版本,不能只畫“最終態(tài)”
二、完美的依賴,致命的循環(huán)
圖上畫了清晰的依賴關(guān)系:訂單→支付→庫(kù)存,箭頭單向,清清楚楚。
上線前壓測(cè),發(fā)現(xiàn)一個(gè)循環(huán)依賴:訂單調(diào)支付,支付調(diào)庫(kù)存,庫(kù)存調(diào)訂單(因?yàn)橐橛唵螤顟B(tài)更新庫(kù)存)。圖上是單向的,代碼里繞回來(lái)了。
結(jié)果呢?一個(gè)請(qǐng)求進(jìn)來(lái),三個(gè)服務(wù)互相調(diào)用,線程卡死,CPU飆升。
排查了三天才發(fā)現(xiàn):庫(kù)存服務(wù)的設(shè)計(jì)文檔里,寫了一句“需要實(shí)時(shí)同步訂單狀態(tài)”,開發(fā)就加了個(gè)RPC調(diào)用。圖上沒畫,評(píng)審沒人發(fā)現(xiàn)。
教訓(xùn)2:圖畫了不等于對(duì)了,要帶參數(shù)驗(yàn)證
三、高可用畫得漂亮,配置全是默認(rèn)
圖畫了“集群部署”“熔斷降級(jí)”。開發(fā)照著樣例配:熔斷超時(shí)60秒,重試3次。
上線后第一個(gè)小故障:數(shù)據(jù)庫(kù)連接超時(shí)。按理說(shuō)應(yīng)該熔斷降級(jí),返回友好提示。結(jié)果呢?服務(wù)重試3次,每次等60秒,3分鐘過(guò)去,連接池爆了。
事后問(wèn)開發(fā):為什么配60秒?答:樣例里寫的,沒想太多。
教訓(xùn)3:圖畫“什么”不夠,還要畫“怎么配”
四、數(shù)據(jù)流畫清楚了,一致性沒畫
圖畫了數(shù)據(jù)流向:業(yè)務(wù)庫(kù)→同步工具→數(shù)倉(cāng)→報(bào)表。
上線后發(fā)現(xiàn),報(bào)表數(shù)據(jù)和業(yè)務(wù)庫(kù)對(duì)不上。排查發(fā)現(xiàn):同步工具是“最終一致性”,延遲有時(shí)候半小時(shí)。業(yè)務(wù)方上午改的數(shù)據(jù),下午報(bào)表才更新。業(yè)務(wù)不接受,說(shuō)“我要實(shí)時(shí)的”。
問(wèn)架構(gòu)師:圖上不是畫了嗎?架構(gòu)師說(shuō):畫了數(shù)據(jù)流,但沒畫一致性要求。你們?cè)趺床辉鐔?wèn)?
教訓(xùn)4:數(shù)據(jù)流圖要標(biāo)注一致性級(jí)別
五、部署圖畫了,沒人能看懂
最后上線前,運(yùn)維問(wèn):這張部署圖,服務(wù)器IP呢?環(huán)境配置呢?啟動(dòng)順序呢?
開發(fā):圖上沒寫,你們自己看著辦吧。
運(yùn)維看著圖,對(duì)著16個(gè)服務(wù),一個(gè)一個(gè)猜:這個(gè)應(yīng)該是先啟動(dòng)的吧?那個(gè)依賴數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)啟動(dòng)了嗎?
上線那天,從晚上10點(diǎn)搞到凌晨4點(diǎn),才把系統(tǒng)跑起來(lái)。
教訓(xùn)5:部署圖要配套部署手冊(cè)
六、5件事,花了800萬(wàn)買來(lái)的
項(xiàng)目復(fù)盤后,我給自己總結(jié)了5條鐵律,現(xiàn)在每次畫圖都會(huì)過(guò)一遍:
1. 圖要分版本
V0.1:MVP能跑的
V0.5:加了高可用、監(jiān)控的
V1.0:理想態(tài)
2. 圖上要標(biāo)參數(shù)
熔斷:超時(shí)200ms,重試1次
集群:3節(jié)點(diǎn),2C4G
數(shù)據(jù)同步:最終一致性,延遲<5min
3. 畫依賴要雙向驗(yàn)證
圖畫單向,代碼可能繞回來(lái)。評(píng)審時(shí)專門查循環(huán)依賴。
4. 數(shù)據(jù)流圖要標(biāo)一致性
強(qiáng)一致?最終一致?延遲多少?
5. 部署圖要配手冊(cè)
環(huán)境要求、啟動(dòng)順序、配置模板、驗(yàn)證方法,缺一不可。
寫在最后
那個(gè)被圖“毀掉”的項(xiàng)目,現(xiàn)在成了我的反面教材。
每次畫圖,我都會(huì)想起那800萬(wàn),提醒自己:
圖不是畫給別人看的,是畫給自己想的。想不清楚的圖,不如不畫。
(本文提到AI工具為Arch架構(gòu)圖工具,用于快速制作不同階段的架構(gòu)視圖)
