银行祖传系统重构实例:创立12年,只支持Python 2,跑着500多个应用程序
作者 | THEHFTGUY、萬佳
提到遺留系統(tǒng),你會(huì)想到什么?
-
還在使用 Java 5 的路過
-
JDK 1.6 的我不說啥了
-
很多坑
-
難維護(hù)
-
從零開始(重寫)
-
盼著 IE 什么時(shí)候不再能使用
-
......
1 遺留系統(tǒng)
對(duì)遺留系統(tǒng),程序員們并不陌生。據(jù)維基百科介紹,遺留系統(tǒng)是一種舊的方法、舊的技術(shù)、舊的計(jì)算機(jī)系統(tǒng)或應(yīng)用程序。張逸認(rèn)為,遺留系統(tǒng)首先是一個(gè)還在運(yùn)行和使用,但已步入軟件生命周期衰老期的軟件系統(tǒng)。它符合所謂的“奶牛規(guī)則”:奶牛逐漸衰老,最終無奶可擠,然而與此同時(shí),飼養(yǎng)成本卻在上升。這意味著遺留系統(tǒng)會(huì)逐漸隨著時(shí)間的推移,維護(hù)成本會(huì)不斷地增加。
在《從 300 萬行到 50 萬行代碼,遺留系統(tǒng)的微服務(wù)改造》一文中,技術(shù)瑣話闡述了遺留系統(tǒng)的一些共同特征。
-
龐大的單體應(yīng)用:遺留系統(tǒng)大多是多年積累下來的“巨無霸”系統(tǒng),以單體應(yīng)用形式呈現(xiàn)。
-
難于修改:多年的代碼累積過程中疏于重構(gòu),導(dǎo)致代碼的可讀性和可擴(kuò)展性較差。
-
維護(hù)成本很高:在龐大的代碼中尋找 bug 的根本原因可能會(huì)比較困難。此外,運(yùn)維也是難題,比如在本章開頭提到的 Perl 系統(tǒng),沒有 APM 工具支持它的監(jiān)控。
-
學(xué)習(xí)成本高昂:由于設(shè)計(jì)陳舊或技術(shù)過時(shí),可能了解遺留系統(tǒng)技術(shù)和業(yè)務(wù)的人已經(jīng)很難找到。
-
缺乏質(zhì)量保障:由于過去缺少投入,許多功能基本上沒有自動(dòng)化測(cè)試來保障質(zhì)量。
事實(shí)上,在傳統(tǒng)企業(yè)甚至互聯(lián)網(wǎng)企業(yè)往往存在大量的遺留系統(tǒng)。這些遺留系統(tǒng)大多都能正常工作,有的可能還運(yùn)行著關(guān)鍵業(yè)務(wù)或者持有核心數(shù)據(jù)。但是,大部分遺留系統(tǒng)通常經(jīng)常存在技術(shù)陳舊、代碼復(fù)雜、難以修改等特點(diǎn)。
我們看到,有的遺留系統(tǒng)給企業(yè)帶來不可挽回的損失:
系統(tǒng)出現(xiàn)故障,當(dāng)年負(fù)責(zé)編寫這個(gè)程序的開發(fā)者卻在 15 年前去世,現(xiàn)在已經(jīng)無人能看懂他的代碼,結(jié)果一個(gè) bug 導(dǎo)致千萬損失。——《程序開發(fā)者去世,代碼沒人懂,一個(gè) bug 導(dǎo)致千萬損失》
還有的遺留系統(tǒng)在企業(yè)技術(shù)變革中慢慢淡出:
筆者曾經(jīng)維護(hù)過一個(gè) Perl 實(shí)現(xiàn)的網(wǎng)站,在 2015 年被解耦前,它已經(jīng)工作了十幾年,為公司占領(lǐng)市場(chǎng)立下了汗馬功勞。奈何技術(shù)陳舊,維護(hù)困難,最后在微服務(wù)化過程中慢慢淡出?!稄?300 萬行到 50 萬行代碼,遺留系統(tǒng)的微服務(wù)改造》
當(dāng)然,也有遺留系統(tǒng)至今活得很好,默默貢獻(xiàn)自己的力量。
2 印象深刻的遺留系統(tǒng)
我在一家銀行工作時(shí),遇到了一套令人印象深刻的遺留系統(tǒng)。
它最初創(chuàng)建于 2008 年(北京奧運(yùn)會(huì)那一年),花費(fèi)數(shù)周時(shí)間進(jìn)行開發(fā)。整套系統(tǒng)具有完整的 CI、CD、單元測(cè)試、代碼審查、自動(dòng)部署等功能。自創(chuàng)建以來,大部分時(shí)間,它的核心基本保持不變,但是外圍有許多改進(jìn)(代碼審查、日志記錄、性能、身份驗(yàn)證等)。
從某種方面說,它相當(dāng)于是公司內(nèi)部的 AWS lambda 等效系統(tǒng)。
你可以編寫一個(gè) Python 腳本(Python 是該系統(tǒng)唯一支持的語言),大約 5 分鐘內(nèi)就能審核完畢并投入生產(chǎn),準(zhǔn)備供世界使用。
這個(gè)系統(tǒng)并不是官方層面的“戰(zhàn)略”解決方案,它不為人知,也沒有做過廣告宣傳。但是,它被頻繁用于多個(gè)業(yè)務(wù)部門,并且不時(shí)有新的發(fā)展。因?yàn)樗糜昧?#xff0c;所以大家都沒法拋棄它。
我們部門有個(gè)暑期實(shí)習(xí)生,他利用這個(gè)系統(tǒng),只花了 3-4 周就基本完成了他們的小項(xiàng)目(實(shí)習(xí)期應(yīng)該有 2-3 個(gè)月)。而同時(shí),其他實(shí)習(xí)生群體還沒有弄清楚如何在“戰(zhàn)略”框架內(nèi)交付應(yīng)用程序。
我最后一次統(tǒng)計(jì)時(shí),那里運(yùn)行著 500 多個(gè)應(yīng)用程序。值得注意的是,生產(chǎn)日志顯示,其中 80% 處于活躍狀態(tài)。
3 外科手術(shù)式維護(hù)
不過,在不斷變化的軟件世界中,所有美好的事物都必須迎來終結(jié)。到頭來, 這套系統(tǒng)還是要重新設(shè)計(jì)或被拋棄,原因如下:
-
Python 2.7 即將壽終正寢
-
身份驗(yàn)證庫(kù)已經(jīng)棄用
-
中間件有很長(zhǎng)時(shí)間沒有重新編譯或升級(jí)了
-
有一些潛在的 UI 改進(jìn)需要完成
為了擁抱變化,這個(gè)系統(tǒng)開始升級(jí)。而在升級(jí)到第一批生產(chǎn)腳本時(shí),我們就遇到問題。
有兩個(gè)用戶每隔 1 小時(shí)就報(bào)告一次問題,我們研究問題后發(fā)現(xiàn)其僅限于 IE 瀏覽器。在 IE 瀏覽器中,某些功能無法正常運(yùn)行。
實(shí)際上,這家銀行很早前就棄用了 IE,轉(zhuǎn)而支持 Chrome 瀏覽器。全公司 25 萬的員工被要求禁止使用 IE 瀏覽器。如果嘗試在 IE 中打開某些站點(diǎn)會(huì)報(bào)錯(cuò),會(huì)提示你改用 Chrome。這對(duì)用戶導(dǎo)航有副作用,因?yàn)樗袃?nèi)容都是相互連接的(想象一下 report.example.com 鏈接到 otherreport.example.com 并調(diào)用 internalapi.example.com,可是某些 URL 是被阻止的)。
好消息是,最近的升級(jí)并沒有倒退回去,而是簡(jiǎn)單解決了這個(gè)問題。IE 被屏蔽,并向 5000 位開發(fā)人員發(fā)出了通知:不再支持 IE 瀏覽器。問題解決了。
供參考:最好硬屏蔽 IE 以改善用戶體驗(yàn),IE 用戶習(xí)慣了在其他瀏覽器中重試。也許最近幾年開發(fā)的內(nèi)部應(yīng)用中有三分之一無法在 Chrome 之外運(yùn)行,不是頁面空白,要么就是到處都有損壞的小部件。
于是,升級(jí)按計(jì)劃進(jìn)行。在最后,我們遇到一個(gè)小麻煩:一個(gè)獨(dú)立的腳本停止工作了 。
該腳本最初創(chuàng)建于十多年前,也就是這個(gè)框架剛創(chuàng)建后的幾個(gè)月內(nèi)。這是最早發(fā)布的應(yīng)用程序之一,也許從歷史上來看是第 8 個(gè)(現(xiàn)在有 500 多個(gè))。
它實(shí)際上不是代碼,而是某種模板。眾所皆知, 該框架帶有自己的模板語言和例程 (二十一世紀(jì)的開發(fā)人員應(yīng)注意:請(qǐng)使用 jinja 進(jìn)行模板化)。已經(jīng)沒有東西還在用這個(gè)模板功能了。團(tuán)隊(duì)進(jìn)行了一些調(diào)整,然后系統(tǒng)又恢復(fù)了正常工作。
最終,升級(jí)完成。
新版同時(shí)支持 Python 2.7 和 Python 3.7,支持 OpenID Connect 和 Kerberos,在各處添加了一些消息和錯(cuò)誤以簡(jiǎn)化使用,還更新了開發(fā)文檔等等……
經(jīng)過 12 年的可靠和忠誠(chéng)的服務(wù),這款舊系統(tǒng)并沒有被棄用。恰恰相反。它還在兢兢業(yè)業(yè)做事,并且肯定還會(huì)再活起碼 12 年,比現(xiàn)在所有的 JavaScript 和戰(zhàn)略框架壽命都更長(zhǎng)。
唯一的缺點(diǎn)是 lambda 請(qǐng)求的啟動(dòng)時(shí)間較長(zhǎng)(基線為 5 秒)。它適合處理偶爾訪問的報(bào)告和 API,不適合用于高性能 API 或緩存,后面的情況下最好使用其他技術(shù),推薦 tornado 用作 Web 服務(wù)器 Web 框架。
4 看遺留系統(tǒng)的“正確姿勢(shì)”
在《關(guān)于遺留系統(tǒng),看看 Google 怎么辦》一文中,Cheng 哥總結(jié)了幾點(diǎn),個(gè)人覺得挺好,分享給讀者。
?保守態(tài)度,不輕易改變
老的系統(tǒng),面對(duì)的場(chǎng)景沒有發(fā)生太大變化,原來什么模式就是什么模式,不要為了改變而改變,比如運(yùn)營(yíng)商的 CT 系統(tǒng)、銀行的核心交易系統(tǒng)等關(guān)乎國(guó)計(jì)民生。
同時(shí),因業(yè)務(wù)特性的原因,本身不會(huì)有很頻繁、很大的變更,這種時(shí)候,現(xiàn)有手段,慢一點(diǎn)、穩(wěn)妥一點(diǎn),哪怕流程繁瑣一點(diǎn)都沒問題。如果改,就可能會(huì)帶來極大的風(fēng)險(xiǎn),也不會(huì)帶來太大收益,不改,也能維護(hù)下去,孰優(yōu)孰劣,自然就清楚了。
現(xiàn)在,運(yùn)維有一種提法,叫做雙態(tài)運(yùn)維,就是針對(duì)系統(tǒng)特點(diǎn),分為穩(wěn)態(tài)和敏態(tài),不同場(chǎng)景采用不同的模式。
?重構(gòu)過渡
如果業(yè)務(wù)場(chǎng)景變化了,要求系統(tǒng)必須能跟上節(jié)奏,這種情況下,建議通過重構(gòu),且逐步遷移的方式過渡。也就是,根據(jù)新的場(chǎng)景,設(shè)計(jì)適應(yīng)的技術(shù)架構(gòu),能夠滿足效率、穩(wěn)定和成本的要求,然后老系統(tǒng)上的業(yè)務(wù)和流量逐步遷移過去。
如果是直接在承載業(yè)務(wù)運(yùn)行的老系統(tǒng)上改,成本和風(fēng)險(xiǎn)會(huì)非常高,實(shí)際情況下是不可行的。
?從現(xiàn)在開始,重視標(biāo)準(zhǔn)統(tǒng)一
前面提到傳統(tǒng)行業(yè)的軟件體系,大多是多廠商建設(shè),標(biāo)準(zhǔn)不統(tǒng)一。但不管是做 DevOps,還是 SRE,甚至最基礎(chǔ)的自動(dòng)化,標(biāo)準(zhǔn)都是前提中的前提。所以,如果當(dāng)前正在規(guī)劃新的技術(shù)體系,或者有針對(duì)某些遺留系統(tǒng)重構(gòu)的機(jī)會(huì),從一開始規(guī)劃好各種標(biāo)準(zhǔn)體系,就非常重要,建設(shè)前沒有標(biāo)準(zhǔn),事后再去統(tǒng)一標(biāo)準(zhǔn),基本就沒有機(jī)會(huì)了。
互聯(lián)網(wǎng)的技術(shù)體系,從最早期的單體架構(gòu),沒有標(biāo)準(zhǔn),到系統(tǒng)拆分的服務(wù)化演進(jìn),形成統(tǒng)一標(biāo)準(zhǔn),再到基于統(tǒng)一標(biāo)準(zhǔn)的運(yùn)維自動(dòng)化、持續(xù)交付以及穩(wěn)定性建設(shè),最終形成大中臺(tái)的體系,也是遵從著這樣一個(gè)過程和規(guī)律走下來。
只不過,互聯(lián)網(wǎng)公司在早期沒有太大的業(yè)務(wù)和技術(shù)的包袱,所以可以小步(甚至大步)快跑,大膽試錯(cuò),快速迭代,整個(gè)過程的進(jìn)展會(huì)更快一些,但是規(guī)律是一樣的。不過,當(dāng)規(guī)模到了一定體量,所面對(duì)的問題,跟傳統(tǒng)行業(yè)也是一樣的,一樣會(huì)有遺留系統(tǒng)。既不可能隨意放棄(還在承載業(yè)務(wù)),也不可能說重構(gòu)就重構(gòu),成本和代價(jià)是必須要考慮的。
對(duì)遺留系統(tǒng),你有什么看法?歡迎留言告訴我們。
總結(jié)
以上是生活随笔為你收集整理的银行祖传系统重构实例:创立12年,只支持Python 2,跑着500多个应用程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蚂蚁科技 Service Mesh 落地
- 下一篇: Spring 自定义注解玩法大全,从入门