微服務改造(戰(zhàn)略篇)

前言

隨著系統(tǒng)業(yè)務的發(fā)展,進而導致系統(tǒng)的架構(gòu)也在不斷的發(fā)生著變化。原代碼以不足以支撐現(xiàn)業(yè)務穩(wěn)定的發(fā)展,于是需要將原.net framework程序進行重構(gòu),改為.net core微服務程序。本篇文章將講述如何從0到1,如何將原來業(yè)務梳理,并重構(gòu)出一個新的微服務,并利用之前講的從0到1devops,將此服務發(fā)布上線。
文章參考歐創(chuàng)新老師,DDD實戰(zhàn)課中的講述思想。我也把一個產(chǎn)品的重構(gòu)分為戰(zhàn)略和戰(zhàn)術(shù)兩個部分。戰(zhàn)略部分從全局的角度描述如何把控一整個產(chǎn)品的生命周期,一個產(chǎn)品是如何從零到一,并高質(zhì)量按時交付的。戰(zhàn)術(shù)部分將主要講述,如何將.net framework應用改為.netcore微服務應用,并使用我之前寫的CI/CD進行發(fā)布上線的。
自己以前一直有個誤區(qū),總覺得作為開發(fā),一定要技術(shù)新,滿嘴技術(shù)名詞高并發(fā),大數(shù)據(jù)才是一個厲害的開發(fā)。而實際上,技術(shù)是服務于產(chǎn)品和用戶的,不落地,產(chǎn)品自身的質(zhì)量不過關(guān),所謂技術(shù)也不過是空談吹牛。事實上,只談技術(shù)不談產(chǎn)品的程序員,大部分寫出來的代碼和實際做事的能力,也是一言難盡。所以,這篇文章更多以產(chǎn)品的視角,來闡述如何高效重構(gòu)一個優(yōu)秀的產(chǎn)品。
我工作經(jīng)歷過三次重構(gòu),第一次單體(.net framework)到單體(.net framework);第二次基于soa的單體(VB .net)到基于soa的單體(.net framework);第三次面向微服務的單體(.net framework)到微服務(.net core);第一次重構(gòu),以我現(xiàn)在視角來看是感覺沒啥效果和意義的;第三次重構(gòu)因為初創(chuàng)公司整個產(chǎn)品體系、敏捷流程還不是很完整,而且整個微服務改造比如預期拆分40個服務,目前只是上線了15個服務,所以還不算特別完整。第二次重構(gòu),10多人的產(chǎn)品、測試、研發(fā)團隊,10來個月,成功保質(zhì)保量重構(gòu)出一個千萬銷售額的產(chǎn)品,我個人認為是比較成功的一次重構(gòu)。所以以第二次重構(gòu)的思想,雜糅第三次重構(gòu)的方案來寫此篇文章。

特別鳴謝:文章中內(nèi)容開發(fā)流程主要為產(chǎn)品經(jīng)理張進成輸出,我只是作為復盤與思考,并寫成文章。
文章中的部署架構(gòu)為同事設(shè)計,我只是做了實現(xiàn)與落地。

戰(zhàn)略比戰(zhàn)術(shù)更為重要,產(chǎn)品本身比技術(shù)實現(xiàn)更為重要。
開發(fā)是解決問題的人員,而不是分析問題的人員,用戶不會關(guān)心你的問題原因及實現(xiàn),只會關(guān)心產(chǎn)品是否好用

重構(gòu)流程

產(chǎn)品重構(gòu)流程.png

上圖是整個產(chǎn)品的開發(fā)周期,產(chǎn)品的功能清單和產(chǎn)品的藍圖是整個重構(gòu)的目標,需清晰明確,并有相關(guān)文檔,不然重構(gòu)很容易跑偏。而且要把控好重構(gòu)的時間節(jié)點,重構(gòu)如果遙遙無期,目標持續(xù)延后。則會影響公司營收與成本,可能實際收益反而不如不重構(gòu)。

重構(gòu)分為局部重構(gòu)和整體重構(gòu),我們的業(yè)務場景屬于整體重構(gòu),而整體重構(gòu)時,很容易受到歷史系統(tǒng)的,歷史包袱的影響。不過個人認為如果整體重構(gòu),還考慮歷史問題,比如從原系統(tǒng)抄代碼、考慮兼容問題,這些都是不可取的,很容易將原來的問題延續(xù)到新系統(tǒng),所以上圖重構(gòu)基本跟開發(fā)一個新產(chǎn)品沒有什么區(qū)別。
整個流程以B端產(chǎn)品為例,并省略了部分內(nèi)容,如上市評估等,但是主體流程無論B端C端,大體應該是相似的。
上圖是我將100多張PPT和10多個文檔進行整合而成,每個環(huán)節(jié)都有具體輸入,出于保密原因無法展示給各位。橘黃色部分實際是整個敏捷開發(fā)體系,為了流程清晰也省略了敏捷的內(nèi)容,所以這個圖內(nèi)容還是挺多的,可以仔細看看。

重構(gòu)策略

部署策略

重構(gòu)之前,需想清楚整體系統(tǒng)架構(gòu)、部署架構(gòu)等內(nèi)容,底層設(shè)計如果出了問題將是災難性的,因為基于底層再進行改動,一是工作量巨大,二是可能為了妥協(xié),做出很多兼容處理導致重構(gòu)失敗。無法達成目標。


系統(tǒng)部署架構(gòu).png

因為我們服務是以后端Api的形式提供訪問接口,所以前端應用有很多種,比如我們的CS客戶端、官網(wǎng)頁面、內(nèi)部CM網(wǎng)站等。圖中展示了用戶訪問這三種應用的過程及部署情況。

  • 用戶訪問官網(wǎng)
    用戶->發(fā)起訪問官網(wǎng)請求->通過nginx配置https轉(zhuǎn)發(fā)到官網(wǎng)應用->官網(wǎng)應用從授權(quán)Pod拉取證書->通過CA公鑰證書驗證用戶登錄->客戶正常訪問到官網(wǎng)應用->官網(wǎng)應用經(jīng)由網(wǎng)關(guān)訪問要訪問的服務(我們實際是直接官網(wǎng)訪問其他服務,不經(jīng)過網(wǎng)關(guān),個人不推薦)
  • 用戶訪問客戶端應用(如電腦QQ)
    用戶->登錄客戶端->通過nginx配置https轉(zhuǎn)發(fā)到授權(quán)Pod->客戶端從授權(quán)Pod拉取證書->通過CA公鑰證書驗證用戶登錄->客戶登錄成功。
    因為客戶端涉及的微服務特別多,故可能存在情況微服務未完全遷移完成,新服務和老服務(接口)共存的情況。所以針對不同操作時,我們通過nginx進行轉(zhuǎn)發(fā),如果客戶端相關(guān)的操作已經(jīng)完成新服務的遷移就使用nginx將其轉(zhuǎn)發(fā)到網(wǎng)關(guān),由網(wǎng)關(guān)服務請求其他的一些服務,將數(shù)據(jù)返回客戶端。如果客戶端相關(guān)的操作還未完成遷移,則nginx將其轉(zhuǎn)發(fā)到老服務,由老服務將數(shù)據(jù)返回到前端。
  • 用戶訪問CM
    用戶訪問CM同用戶訪問官網(wǎng),故不再贅述

此部署策略是一個簡化版本,比如未展示高可用,未實現(xiàn)serviceMesh,未展示后端應用依賴的服務,如kafka、mongo、es、redis等。此文是為了更容易理解,而且我們第一版服務確實也還未實現(xiàn)serviceMesh,其他依賴的kafka、mongo等部署策略,不同業(yè)務場景部署也不一樣故省略了,只展示主體架構(gòu)。
正常情況服務的路由應該是通過網(wǎng)關(guān)進行轉(zhuǎn)發(fā),但是我們因為一些早期設(shè)計和其他的一些原因?qū)⒙酚晒δ苤苯臃旁诹薾ginx,網(wǎng)關(guān)服務Pod可以當作一個加強的BFF。(基礎(chǔ)稍弱的同學,此處可能會有一些疑惑,可能看了戰(zhàn)術(shù)設(shè)計,這里就明白了)

分拆策略

微服務的改造不是一蹴而就的,因為整個工程量還是比較大的,所以我們會面臨幾個問題。

  • 如何保證線上業(yè)務正常運行,同時完成服務的改造上線?
  • 服務上線后如果出現(xiàn)問題,如何快速回滾?
  • 服務上線后如何保證不出現(xiàn)大規(guī)模事故?
    針對這幾個問題,我們想到的粗略解決方案是:
  • 服務改造后上線,可能存在數(shù)據(jù)遷移和應用遷移兩部分內(nèi)容,數(shù)據(jù)遷移的工作可以參考 MongoDb數(shù)據(jù)庫遷移與方式,無論mysql、mongo還是啥,其遷移思路基本都是一樣的。
  • 因為同時維護老的數(shù)據(jù)庫和新的數(shù)據(jù)庫,老的服務和新的服務也同時存活,當出現(xiàn)問題時可以直接切換nginx進行快速的應用切換。待新服務穩(wěn)定運行一段時間后,可以停掉老服務。如果此后新服務出現(xiàn)問題,可以利用k8s的滾動更新機制,切換鏡像就可以很方便的回滾了。
  • 為了不造成大規(guī)模事故,新服務只能分批上線,盡量控制影響范圍。所以最新上線的服務不能依賴其他服務,比如先上線授權(quán)服務、驗證碼服務等基礎(chǔ)功能服務。所以服務改造,需要從基礎(chǔ)服務入手,基礎(chǔ)服務完成后,再進行依賴于基礎(chǔ)服務的相關(guān)為服務改造

發(fā)布策略

前文我們講述了如何從0到1建設(shè)自己企業(yè)內(nèi)部使用的devops,同樣的,原來的應用經(jīng)過微服務改造后,被拆分成了幾十上百個微服務應用,發(fā)布時不可能通過人肉進行發(fā)布,所以我們使用devops進行自動發(fā)布。


image.png

我們首先從git倉庫拉取代碼,然后經(jīng)過代碼掃描,代碼分析然后生成鏡像,發(fā)布到測試環(huán)境K8s集群,經(jīng)過測試人員測試通過后,我們從鏡像倉庫拉取鏡像,發(fā)布到預發(fā)環(huán)境,預發(fā)環(huán)境再進行一輪簡單測試,測試通過后。從鏡像倉庫拉取鏡像發(fā)布到正式k8s集群。

可能針對這個發(fā)布流程,大家還是有很多的疑問。比如我某個倉庫代碼一天部署1000次,難道我鏡像倉庫要保存1000個
鏡像版本?那么多鏡像,我正式環(huán)境怎么知道哪些是穩(wěn)定發(fā)布的鏡像,哪些是測試的鏡像?上百個服務,我jenkinsfile每個微服務項目都一個?那如果修改維護jenkinsfile豈不是每個項目都要改?發(fā)布回滾怎么做?藍綠、灰度怎么弄?開發(fā)分支管理怎么處理?

鏡像管理

鏡像管理.png

我們將所有非正式版的鏡像都標記為Tag:latest,這樣我鏡像倉庫就只有一個用于測試的鏡像,版本為latest,避免了我鏡像倉庫太多鏡像,也避免了我k8s集群服務器,過多的鏡像導致磁盤占滿。當測試通過后,我們用jenkins進行發(fā)布時,勾選“tagOfficialImage”這個勾選框,這樣我們就對鏡像打一個tag,tag格式為“版本.日期.git提交次數(shù)”。同時git代碼上,打上相同的tag。
這樣我們再預發(fā)布、正式發(fā)布時,找到git項目上最新的tag,因為git、鏡像tag同名,所以我們發(fā)布的也是最新的鏡像。如果要回滾,同理,jenkins上選擇相應的git項目的tag,根據(jù)這個tag去鏡像倉庫找相同名稱的鏡像就可以回滾到相應的版本了。

分支管理

因為git分支有很多種類型。我們是分了如下幾類:迭代開發(fā)分支(12Sp2)、修復分支(hotfix)、專項分支(feature)、主分支(master)。一般,master分支作為主干分支,需要穩(wěn)定安全,所以一般開發(fā)人員不允許直接推送代碼到master分支。所以每個迭代開始就按迭代日期創(chuàng)建新的分支,比如12月第2個迭代,就增加分支12Sp2。等迭代結(jié)束時,再由SM將審核通過的12Sp2代碼合并到master,這時候給客戶的就是穩(wěn)定的master的代碼。
在測試環(huán)境用jenkins發(fā)布部署時,就用12Sp2,因為開發(fā)過程中會存在反復修改與調(diào)試的情況。如果用master分支,改一個BUG需要SM審核一次代碼,合一次代碼,開發(fā)測試人員還得等代碼合并后,才能重新進行測試,造成很大的內(nèi)部損耗。而12Sp2改一次,發(fā)布一次。真正做到持續(xù)部署,等到測試通過,就將代碼合并master,并打上tag進行發(fā)布,這樣只需要一次代碼合并審核。

jenkinsfile管理

配置pipeline需要在項目中配置一個Jenkinsfile文件,存放pipeline腳本(不考慮job中直接寫腳本的方式,維護起來太繁瑣)??赡芎芏嗤瑢W這個時候會想到shared library。但是shared library只能解決功能復用的問題,解決不了jenkinsfile復用的問題。于是我參考這個文章# Jenkins的Pipeline腳本在美團餐飲SaaS中的實踐做了如下處理。

image.png

至于灰度發(fā)布,可以使用nginx,也可以直接使用k8s的ingress,本質(zhì)也是nginx。藍綠發(fā)布也只是把流量切分到不同的k8s集群。因為這塊還沒實踐,所以先不贅述,免得誤導,但是感覺這一塊并不復雜,網(wǎng)上資料,相信聰明的你,應該足夠搞定了。

總結(jié)

文章用一個比較全局的視角描述了如何進行微服務重構(gòu)與發(fā)布。但是沒有具體落地實現(xiàn),相信你還是有很多困惑,不過沒有關(guān)系,這個只需要了解是怎么回事就行,了解大概原理和方案就足夠了。具體的落地和實現(xiàn)會在戰(zhàn)術(shù)篇中講述,同時會附上git代碼和地址。

\color{red}{最后,強調(diào)一句,我長得很帥。畫圖是用processon這個工具,各位可以使用這個邀請鏈接加入processon,我就可以白嫖三個免費的文件,不用沖VIP了。} 邀請鏈接,

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容