承接遺留系統(tǒng)運(yùn)維工作的經(jīng)驗(yàn)
眾所周知,改造遺留系統(tǒng)并非易事,如果該系統(tǒng)沒(méi)有良好的架構(gòu)和編碼,那么在這基礎(chǔ)上做功能升級(jí)改造,往往比做全新系統(tǒng)更加費(fèi)時(shí)費(fèi)力。我的團(tuán)隊(duì)最近承接了一個(gè)這樣的平臺(tái)升級(jí)改造項(xiàng)目,該平臺(tái)前后已經(jīng)歷四五家供應(yīng)商歷時(shí)七八年的不斷修改,可維護(hù)性極差。在進(jìn)行升級(jí)改造的同時(shí),我們更“有幸”直接承擔(dān)了該系統(tǒng)的各項(xiàng)線上運(yùn)維工作,真真切切體驗(yàn)了陷入“軟件泥潭”的感受。
一、那些令我們難忘的經(jīng)歷
在項(xiàng)目一開(kāi)始,便得知該系統(tǒng)前團(tuán)隊(duì)合同已到期會(huì)直接撤出,于是我們快速進(jìn)行了交接,對(duì)系統(tǒng)做升級(jí)改造之前,先展開(kāi)運(yùn)維工作。以下為我們經(jīng)歷的幾個(gè)片段,該系統(tǒng)的威力略見(jiàn)一斑。
1)“定時(shí)炸彈”
系統(tǒng)里有這樣一個(gè)功能,可以定時(shí)修改首頁(yè)某區(qū)域的內(nèi)容。有這么一次,運(yùn)營(yíng)人員通過(guò)后臺(tái)上傳要修改的內(nèi)容后,發(fā)現(xiàn)上傳錯(cuò)了,但系統(tǒng)卻沒(méi)有提供刪除和更新已上傳內(nèi)容的功能,好在可以修改定時(shí)時(shí)間,于是運(yùn)營(yíng)人聰明地把定時(shí)時(shí)間設(shè)置為一年后生效,從而避免了系統(tǒng)首頁(yè)被改為錯(cuò)誤信息。一年后本團(tuán)隊(duì)接手了,首頁(yè)莫名被修改,原本設(shè)置該定時(shí)任務(wù)的人員早已離職,留下我方研發(fā)加運(yùn)維人員努力排查問(wèn)題至深夜。
2)“扯謊”的流水線
在交接運(yùn)維工作時(shí)被告知客戶需要頻繁做各種活動(dòng),每次活動(dòng)都是要做代碼修改和重新上線的。本團(tuán)隊(duì)一度慶幸該系統(tǒng)盡管老舊,但還是可以通過(guò)Jenkins進(jìn)行上線工作的。
但接手后發(fā)現(xiàn)我們“天真”了,該系統(tǒng)由4個(gè)子系統(tǒng)約二十多個(gè)單獨(dú)部署的服務(wù)組成,使用的語(yǔ)言和框架各不相同。當(dāng)?shù)谝淮斡昧魉€進(jìn)行上線工作時(shí),我們以為點(diǎn)了按鈕就大功告成了,結(jié)果發(fā)現(xiàn)最后只有少部分服務(wù)部署提示成功,而更過(guò)分的是,這些提示成功的部署實(shí)際有可能是失敗了,而一些提示失敗的實(shí)際上卻是部署成功了。當(dāng)我們聯(lián)系前運(yùn)維團(tuán)隊(duì)時(shí),被告知由于年久失修,這些流水線有的能用,有的不能用,有時(shí)好用,有時(shí)不好用,上線時(shí)候讓開(kāi)發(fā)備著。為了不影響第二天白天的正常使用,我方研發(fā)加運(yùn)維人員上線到天明。
3)尷尬的日志和難纏的注釋
該系統(tǒng)常常出現(xiàn)一些不大不小的錯(cuò)誤,不致命但是會(huì)被客戶業(yè)務(wù)部門投訴。例如線索模塊負(fù)責(zé)處理線索數(shù)據(jù)并向下游傳送,每周總會(huì)莫名其妙丟失幾條數(shù)據(jù),于是我們展開(kāi)了問(wèn)題排查工作。首先就是去查看日志,當(dāng)找到處理線索的日志后,我們震驚了,只見(jiàn)日志里滿屏顯示著大寫的“END”,既沒(méi)有時(shí)間信息也沒(méi)有相關(guān)處理的信息,只是每條數(shù)據(jù)成功處理完print “END”,找不到任何有用信息。
當(dāng)我們?nèi)シ创a時(shí),名不達(dá)意自是意料之中,好在有注釋。不過(guò)注釋是亂碼,這自然難不住我們,修改編碼嘛。修改后又驚奇的發(fā)現(xiàn),一部分注釋變成中文可讀了,而另一部分卻變成了另一種亂碼,不管怎么改,總是只有一部分注釋變?yōu)檎#渌詾閬y碼。沒(méi)想到之前的幾波研發(fā)團(tuán)隊(duì)寫注釋竟然還使用各自不同的編碼。
二、原因初探
那么這套系統(tǒng)怎么會(huì)發(fā)展到如下境地呢,冰凍三尺,非一日之寒。從我們最近的觀察,可能有以下幾點(diǎn)值得注意:
1)缺乏長(zhǎng)遠(yuǎn)的規(guī)劃,各種“債”不斷堆積
企業(yè)的復(fù)雜性,使交付團(tuán)隊(duì)處在一個(gè)艱難的環(huán)境,面對(duì)業(yè)務(wù)側(cè)頻繁的、緊急的業(yè)務(wù)需求,交付團(tuán)隊(duì)經(jīng)常靠技術(shù)人員強(qiáng)行對(duì)應(yīng),導(dǎo)致了各種臨時(shí)方案不斷堆積,各種“債”也隨之積攢,系統(tǒng)變得越來(lái)越難以維護(hù)。
另一個(gè)現(xiàn)象是,由于系統(tǒng)各種依賴關(guān)系太復(fù)雜,每一家新供應(yīng)商基本都不愿去修改或優(yōu)化之前的代碼,做功能時(shí)候都只增不減。以至于系統(tǒng)管理后臺(tái)出現(xiàn)出現(xiàn)多個(gè)同名的模塊的詭異現(xiàn)象,其功能又全然不同,完全分不清楚哪個(gè)是在用的。久而久之,該系統(tǒng)的運(yùn)營(yíng)工作難度也越來(lái)越大,換了運(yùn)營(yíng)人員肯定玩不轉(zhuǎn)。
2)功能不夠運(yùn)維湊
由于系統(tǒng)功能不夠閉環(huán),外加開(kāi)發(fā)階段過(guò)后只剩下運(yùn)維人員支撐,導(dǎo)致了很多緊要需求通過(guò)運(yùn)維人員改庫(kù)來(lái)實(shí)現(xiàn)。當(dāng)通過(guò)改庫(kù)和臨時(shí)修改代碼來(lái)應(yīng)對(duì)需求變成了日常例行操作,整個(gè)系統(tǒng)也變得更加脆弱了。
三、應(yīng)對(duì)策略與建議
最好的策略自然是不要過(guò)早承接遺留系統(tǒng)的運(yùn)維工作,至少要等升級(jí)改造工作開(kāi)展到一定階段,新系統(tǒng)上線后再去承接。但現(xiàn)實(shí)往往骨感,如果不得已需要立刻交接,那么建議至少做好以下幾點(diǎn):
1)拉長(zhǎng)交接期,在交接期做足功課
將交接列表做得詳細(xì)一些,并做好交接期間的日程安排,確保雙方團(tuán)隊(duì)有充足的溝通,從業(yè)務(wù)和技術(shù)層面都有詳細(xì)的講解。交接列表參考示例見(jiàn)文末附錄,如果項(xiàng)目使用到了一些看板或相關(guān)需求開(kāi)發(fā)管理工具也注意一并交接。
對(duì)于交接列表中的文檔,很可能對(duì)方缺失嚴(yán)重,那么一方面是需要讓對(duì)方盡力補(bǔ)齊相關(guān)文檔,另一方面則要針對(duì)列表中的各項(xiàng)專題開(kāi)展交接溝通會(huì),盡量獲取到更多的知識(shí),在交接過(guò)程中注意做好總結(jié)。
2)確保開(kāi)發(fā)人員的可調(diào)試環(huán)境能正常運(yùn)行
這點(diǎn)很重要,盡管在交接階段已經(jīng)拿到了大量文檔,但文檔的內(nèi)容和當(dāng)前代碼真的一致嗎,緊急出現(xiàn)的BUG如何快速排查和修復(fù)?這些終究需要可運(yùn)行可調(diào)試的代碼來(lái)給出答案。以本項(xiàng)目為例,交接期僅有Tech Lead和一個(gè)運(yùn)維同事開(kāi)展與前團(tuán)隊(duì)所有的技術(shù)和運(yùn)維交接工作,面對(duì)多種語(yǔ)言多種框架實(shí)現(xiàn)的各類代碼有些力不從心,好在果斷要求對(duì)方協(xié)助,在我們的研發(fā)機(jī)器上實(shí)現(xiàn)各類代碼的運(yùn)行和調(diào)試。交接完就立刻趕上雙十一活動(dòng)上線,結(jié)果到了凌晨搶購(gòu)時(shí)間點(diǎn),產(chǎn)品購(gòu)買頁(yè)面的購(gòu)買按鈕仍是置灰狀態(tài)無(wú)法點(diǎn)擊,于是現(xiàn)場(chǎng)調(diào)試,發(fā)現(xiàn)了系統(tǒng)處理時(shí)間的BUG并及時(shí)修復(fù),才使業(yè)務(wù)未受到明顯影響。
3)完善監(jiān)控和日志功能,變被動(dòng)為主動(dòng)
這點(diǎn)不用過(guò)多解釋,通過(guò)對(duì)監(jiān)控的完善和日志的完善,使團(tuán)隊(duì)能夠及早發(fā)現(xiàn)系統(tǒng)的各種問(wèn)題,在出現(xiàn)異常時(shí)能夠追查原因,不至于手足無(wú)措。
4)與前團(tuán)隊(duì)維護(hù)好關(guān)系
雖然這不是一個(gè)技術(shù)舉措,但有時(shí)候卻非常有效,畢竟前團(tuán)隊(duì)經(jīng)過(guò)摸爬滾打,已經(jīng)熟悉了這個(gè)系統(tǒng)的秉性。當(dāng)遇到一些緊急問(wèn)題時(shí)候,他們的一句建議可能省去一天的錯(cuò)誤排查。
四、后記
盡管這樣一個(gè)“軟件泥潭”讓團(tuán)隊(duì)的行動(dòng)很艱難,但我們對(duì)各種企業(yè)級(jí)問(wèn)題的處理和解決增長(zhǎng)了經(jīng)驗(yàn),我想團(tuán)隊(duì)中每個(gè)人都會(huì)從中有所收獲。在系統(tǒng)運(yùn)維工作順利展開(kāi)后,團(tuán)隊(duì)終于開(kāi)啟了遺留系統(tǒng)改造之旅。
附錄1: 交接列表示例(設(shè)計(jì)與開(kāi)發(fā))
類別 | 內(nèi)容 |
項(xiàng)目管理 | 項(xiàng)目日程 |
會(huì)議記錄 | |
體制圖 | |
項(xiàng)目要件 | 業(yè)務(wù)功能清單 |
業(yè)務(wù)流程圖 | |
需求變更記錄 | |
操作說(shuō)明書/用戶手冊(cè) | |
常見(jiàn)問(wèn)題一覽 | |
界面設(shè)計(jì) | UE設(shè)計(jì)稿 |
高保真畫面設(shè)計(jì)稿 | |
需求變更一覽 | |
系統(tǒng)設(shè)計(jì) | 系統(tǒng)架構(gòu)設(shè)計(jì)圖 |
部署架構(gòu)圖 | |
DB關(guān)聯(lián)圖(ER圖)和DB詳細(xì)設(shè)計(jì) | |
系統(tǒng)間集成關(guān)系圖 | |
對(duì)接系統(tǒng)一覽表和對(duì)接系統(tǒng)接口清單 | |
開(kāi)發(fā)制作 | 源代碼 |
代碼運(yùn)行說(shuō)明 | |
測(cè)試 | 系統(tǒng)測(cè)試用例與系統(tǒng)測(cè)試報(bào)告書 |
性能測(cè)試用例與性能測(cè)試報(bào)告書 | |
用戶測(cè)試用例 | |
用戶測(cè)試簽字 |
附錄2: 交接列表示例(運(yùn)維相關(guān))
類別 | 內(nèi)容 |
上線相關(guān) | 上線判定表 |
上線操作記錄 | |
歷次上線版本說(shuō)明 | |
臨時(shí)對(duì)應(yīng)體制 | |
基礎(chǔ)設(shè)施 | 硬件資源一覽 |
軟件資源一覽 | |
服務(wù)器/系統(tǒng)賬號(hào)權(quán)限 | |
系統(tǒng)工具 - 付費(fèi)/免費(fèi)軟件 | |
運(yùn)維體制 | 運(yùn)維工作一覽表 |
近半年運(yùn)維工作應(yīng)對(duì)流程 | |
運(yùn)維體制 | |
故障對(duì)應(yīng)流程 | |
SLA(服務(wù)水平協(xié)議) | |
DEVOPS(開(kāi)發(fā)運(yùn)維一體化) | CI/CD工具與使用 |
監(jiān)控工具 | |
備份管理 | |
代碼庫(kù)與分支管理 | |
數(shù)據(jù)庫(kù)相關(guān)配置與策略 |