自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

遺留系統(tǒng)的服務(wù)拆分

原創(chuàng) 精選
開發(fā)
我們正在書寫、即將面對(duì)、正在面對(duì)遺留系統(tǒng)。在與遺留系統(tǒng)的相愛相殺中,需要我們基于項(xiàng)目目標(biāo)和現(xiàn)狀、結(jié)合過往經(jīng)驗(yàn)、經(jīng)過剪裁和取舍,才能迎面不斷出現(xiàn)的挑戰(zhàn)。

最近一年來,我所在的項(xiàng)目為一個(gè)傳統(tǒng)行業(yè)客戶的 IT 核心系統(tǒng)做遺留系統(tǒng)改造,我參與了該系統(tǒng)一個(gè)業(yè)務(wù)模塊的拆分和服務(wù)化,在這過程中落地了一些有意思的實(shí)踐,特此記錄下來和大家分享。

項(xiàng)目背景

這是一個(gè)運(yùn)行了至少 15 年的單體系統(tǒng),采用的技術(shù)棧是 JDK8、Servlet、JSP、Oracle、JDBC、存儲(chǔ)過程、Weblogic,從這些關(guān)鍵詞就能感受到它的滄桑感。整個(gè)系統(tǒng)都在一個(gè)代碼倉庫中,或按業(yè)務(wù)或按功能劃分成了 30 多個(gè) maven 模塊,模塊間可以任意調(diào)用彼此的方法,也可以隨意訪問彼此業(yè)務(wù)的數(shù)據(jù)庫表。最讓人糟心的是,大部分的業(yè)務(wù)邏輯都寫在復(fù)雜的 SQL 語句和存儲(chǔ)過程里,幾百行的 SQL、一堆表的 join、層層調(diào)用的存儲(chǔ)過程比比皆是。當(dāng)然,該系統(tǒng)也沒有落下“沒有自動(dòng)化測(cè)試”這個(gè)遺留系統(tǒng)的典型標(biāo)簽。

圖片

圖1 單個(gè)代碼倉庫里包含的各種業(yè)務(wù)模塊和技術(shù)模塊

客戶PO是一個(gè)對(duì)技術(shù)有理想有抱負(fù)的人物,不希望這個(gè)系統(tǒng)再繼續(xù)腐化下去,所以找到我司對(duì)該系統(tǒng)進(jìn)行現(xiàn)代化改造,其中一個(gè)落地措施就是對(duì)這個(gè)單體系統(tǒng)進(jìn)行拆分和服務(wù)化。經(jīng)過挑選,A 業(yè)務(wù)成為了這一批改造的試點(diǎn)對(duì)象。

這次拆分的目標(biāo)是:將 A 業(yè)務(wù)的代碼和數(shù)據(jù)庫表從原有代碼和數(shù)據(jù)庫中拆分出來,形成獨(dú)立的 A 服務(wù)及其數(shù)據(jù)庫,實(shí)現(xiàn) A 業(yè)務(wù)的代碼獨(dú)立、數(shù)據(jù)獨(dú)立、部署獨(dú)立。

圖片

圖2 拆分目標(biāo)

總體策略

這次服務(wù)拆分的策略歸納起來有三條:

(1) 先代碼拆分、后數(shù)據(jù)拆分

代碼和數(shù)據(jù)是服務(wù)拆分的兩個(gè)重要物理實(shí)體。先拆代碼還是先拆數(shù)據(jù),在《Monolith to Microservices》中介紹了這兩種方式的優(yōu)劣。我們考慮到在現(xiàn)有代碼極其復(fù)雜的前提下,先拆數(shù)據(jù)會(huì)給代碼帶來更大的復(fù)雜性,并且在出現(xiàn)問題、需要回滾的情況下,拆分前后的數(shù)據(jù)一致性也十分困難,因此我們選擇了先代碼拆分的策略。

圖片

圖3 先代碼拆分、后數(shù)據(jù)拆分

(2) 以單個(gè)頁面請(qǐng)求為單位進(jìn)行拆分

拆分工作由 10 位開發(fā)人員承擔(dān),如何劃分大家工作內(nèi)容呢:按數(shù)據(jù)庫表?按 Servlet?按頁面?我們選擇的是按請(qǐng)求來劃分。A 業(yè)務(wù)的后端 Servlet 提供了近 300 個(gè)功能,每個(gè)功能對(duì)應(yīng)一個(gè)前端請(qǐng)求URL。我們以單個(gè)請(qǐng)求為顆粒度劃分開發(fā)任務(wù),并按我們熟悉的敏捷開發(fā)方式創(chuàng)建 Jira 卡片、安排到每個(gè)迭代中。按這樣的顆粒度劃分后,大多數(shù)開發(fā)任務(wù)可以對(duì)應(yīng)到1、2、3、5天的工作量,非常有利于安排每個(gè)迭代的內(nèi)容、分批上線、形成緊湊的工作節(jié)奏、縮小每個(gè)開發(fā)任務(wù)的測(cè)試范圍。

(3) 代碼先完整復(fù)制,再修改

新服務(wù)的框架搭起來以后,是一開始就把 A 業(yè)務(wù)的代碼復(fù)制到新創(chuàng)建的服務(wù)中,還是在做開發(fā)任務(wù)的時(shí)候才把涉及到的代碼復(fù)制到新服務(wù)中再做修改?我們選擇的是前者,因?yàn)楹笳咴诙嗳瞬⑿虚_發(fā)的時(shí)候會(huì)遇到復(fù)制沖突的問題,與其這樣,不如一開始就整體復(fù)制好,在做開發(fā)任務(wù)的時(shí)候再修改涉及到的代碼。當(dāng)然,一開始還需要把一些公共代碼或者依賴的其他業(yè)務(wù)代碼也復(fù)制過來,以保證 A 服務(wù)的代碼能編譯通過。

使用 Feature Toggle 用于功能回滾

只要是對(duì)代碼的改動(dòng),就有可能引入 bug?!?我說的

雖然Dev、QA團(tuán)隊(duì)盡力最大努力,但依舊無法避免拆分出來的服務(wù)上線后出bug,一旦出現(xiàn),需要盡快切換回原有系統(tǒng)以減少對(duì)業(yè)務(wù)的影響。結(jié)合我們以頁面請(qǐng)求為單位進(jìn)行拆分的方式,我們引入 feature toggle 作為切換新舊系統(tǒng)的開關(guān),控制前端發(fā)來的請(qǐng)求是發(fā)送給原有系統(tǒng)還是發(fā)送給拆分出來的服務(wù)。

圖片

圖4 使用 Feature Toggle 切換新舊系統(tǒng)

在實(shí)現(xiàn)的時(shí)候,所有請(qǐng)求默認(rèn)還是先發(fā)給原有系統(tǒng),我們?cè)谠邢到y(tǒng)的后端新增了一個(gè)請(qǐng)求過濾器,在過濾器中提取請(qǐng)求的 URL,根據(jù) URL 判斷:如果是已經(jīng)拆分出去的功能請(qǐng)求,并且數(shù)據(jù)庫中記錄的 toggle 是開啟的,則將請(qǐng)求轉(zhuǎn)發(fā)給新服務(wù)處理;反之依舊交由原有系統(tǒng)處理。

既然將回滾作為快速恢復(fù)功能的手段,那引入了一項(xiàng)開發(fā)約定:在拆分過程中,只允許修改新服務(wù)的代碼,不允許修改原有系統(tǒng)的代碼。

Feature Toggle 不僅在處理線上問題時(shí)可以用來及時(shí)止血,還給團(tuán)隊(duì)帶來了額外的好處:

  • 在上線前,Dev和QA可以切換開關(guān),快速比對(duì)某個(gè)功能的改造前后的效果是否一致。?
  • 到了上線時(shí)間,但測(cè)試尚未充分,或者在年底大促的業(yè)務(wù)高峰期擔(dān)心引入 bug 影響業(yè)務(wù)的時(shí)候,就出現(xiàn)了“開發(fā)完成但不能上線”的情況,這時(shí)關(guān)閉對(duì)應(yīng)的 toggle 即可讓拆分后的功能暫緩上線。?

使用代碼分析工具簡(jiǎn)化數(shù)據(jù)庫表的使用分析

每一個(gè)拆分任務(wù)的重點(diǎn)工作之一,是識(shí)別該功能讀寫的表是否是 A 業(yè)務(wù)的表。因?yàn)橹挥?A 業(yè)務(wù)的表,最終才會(huì)拆分到 A 數(shù)據(jù)庫中;反之如果不是 A 業(yè)務(wù)的表,被視為只有原有系統(tǒng)才能直接讀寫,在 A 服務(wù)中無法讀寫,需要改為調(diào)用原有系統(tǒng)新增加 API 的方式來取代原有的數(shù)據(jù)操作。

如果是一個(gè)簡(jiǎn)單的功能,尚可通過肉眼查看代碼來識(shí)別都操作了哪些表。但凡功能稍微復(fù)雜,人工查看的效率和準(zhǔn)確性就大打折扣甚至不可行。好在我司的一個(gè)大牛為該項(xiàng)目開發(fā)了代碼分析工具,它可以通過分析編譯后的 Java 字節(jié)碼文件,得到方法調(diào)用鏈上所有方法的調(diào)用關(guān)系,以及 SQL 和存儲(chǔ)過程里讀寫的表,并將分析結(jié)果形成一個(gè)樹形結(jié)構(gòu)并以 xmind 或者 svg 的格式保存下來。開發(fā)人員有了分析結(jié)果,不費(fèi)吹灰之力就能知道當(dāng)前拆分的功能涉及哪些表,以及在調(diào)用哪個(gè)方法的時(shí)候用到了這些表,從而對(duì)接下來要拆分的代碼心中有數(shù)。

圖片

圖5 一個(gè)稍微復(fù)雜一點(diǎn)的方法調(diào)用鏈分析結(jié)果

如果沒有這個(gè)分析工具,Dev 可能要花好幾天甚至好幾周去分析一個(gè)復(fù)雜的待拆分功能,而現(xiàn)在只需要幾秒鐘,分析結(jié)果就呈現(xiàn)在眼前。這個(gè)工具被客戶譽(yù)為“神器”,我們?cè)谟玫臅r(shí)候也時(shí)常感嘆:“自動(dòng)化真香!”

使用 Code Owner 保持新舊代碼的一致

在拆分過程中,如果有新需求涉及 A 業(yè)務(wù)的變更,則原有系統(tǒng)和新服務(wù)中的代碼都需要同步修改,否則就會(huì)出現(xiàn)二者的功能不一致:

  • 如果只修改了原有系統(tǒng)而未修改新服務(wù),那么該功能在拆分改造后,功能就會(huì)和改造前存在差異。?
  • 如果只修改了新服務(wù)而未修改原有系統(tǒng),那么一旦 toggle 關(guān)閉,則原有系統(tǒng)則無法提供新需求的功能。?

客戶使用的版本控制系統(tǒng)是 BitBucket,并且以提交 Pull Request(PR)的方式合并新代碼。因此我們使用了 BitBucket 的 Code Owner 功能(Github、Gitlab 也有該功能)監(jiān)控原有系統(tǒng)中 A 業(yè)務(wù)涉及的模塊和文件夾,同時(shí)也監(jiān)控了新服務(wù)所有代碼,并將拆分團(tuán)隊(duì)的兩位骨干Dev設(shè)置為 Code Owner。這樣一旦在 PR 中包含被監(jiān)控代碼的改動(dòng),則會(huì)自動(dòng)把 Code Owner 設(shè)置為 PR 的 Reviewer,Code Owner 收到系統(tǒng)通知后會(huì)檢查代碼是否做了同步修改。如果代碼修改未同步,則不允許合并 Pull Request。

結(jié)語

讓我們面對(duì)現(xiàn)實(shí)吧,我們今天所做的一切就是在編寫明天的遺留系統(tǒng) —— Martin Fowler

我們正在書寫、即將面對(duì)、正在面對(duì)遺留系統(tǒng)。在與遺留系統(tǒng)的相愛相殺中,需要我們基于項(xiàng)目目標(biāo)和現(xiàn)狀、結(jié)合過往經(jīng)驗(yàn)、經(jīng)過剪裁和取舍,才能迎面不斷出現(xiàn)的挑戰(zhàn)。我以此文拋磚引玉,歡迎大家交流拍磚。

責(zé)任編輯:趙寧寧 來源: Thoughtworks洞見
相關(guān)推薦

2010-09-06 16:35:58

SQL函數(shù)

2021-01-15 11:01:42

IT系統(tǒng)漏洞網(wǎng)絡(luò)攻擊

2022-01-13 09:49:40

遺留系統(tǒng)交接開發(fā)

2023-06-25 12:22:25

IT領(lǐng)導(dǎo)者CIO

2018-05-03 15:34:34

組件測(cè)試遺留系統(tǒng)微服務(wù)

2024-04-12 10:03:48

2022-08-24 09:50:40

系統(tǒng)運(yùn)維

2021-07-09 05:25:48

CIO遺留系統(tǒng)現(xiàn)代化用戶體驗(yàn)

2022-11-09 10:02:21

CDC遺留系統(tǒng)

2022-03-31 08:15:38

微服務(wù)服務(wù)拆分架構(gòu)

2014-02-13 09:47:41

GartnerERP云ERP

2021-06-27 17:20:20

遺留系統(tǒng)隱形成本CIO

2013-09-12 09:39:38

遺留系統(tǒng)云遷移API

2020-11-30 10:13:17

ITCIO首席信息官

2021-12-27 11:02:00

首席信息官技術(shù)發(fā)展企業(yè)管理者

2013-09-16 13:18:28

遺留系統(tǒng)系統(tǒng)遷移

2010-09-01 16:08:03

遺留系統(tǒng)Java

2013-11-11 09:59:29

Boni Satani遺留系統(tǒng)系統(tǒng)遷移

2021-06-10 11:12:23

微服務(wù)微服務(wù)架構(gòu)

2020-03-09 14:10:48

代碼開發(fā)工具
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)