轉載本文需注明出處:EAII企業架構創新研究院,違者必究。如需加入微信群參與微課堂、架構設計與討論直播請直接回復公眾號“EAII企業架構創新研究院”。(微信號:eaworld)
各位群友,下午好。今天要和大家分享的話題是“基於微服務的企業應用架構設計范式”。
這個話題曾經分別在PWorld大會和QCon2016大會上做過分享,得到不錯的反響,因此借着今天這個機會也分享給大家。
微服務好像是這兩年突然火起來的,其實和很多其他架構風格一樣,微服務架構也是我們在用軟件改變世界的過程中,為了適應內外部環境的變化,而逐漸演化出的一種當前的最佳實踐。
比如SOA,比如J2EE,比如傳統分布式;微服務架構和它們都有千絲萬縷的聯系。
前幾天我們的CTO焦總發表了一篇文章:《從前世看今生,從JavaEE到微服務》,推薦大家看看,對微服務的來龍去脈講得非常清楚。
這些年來,我們幫助一些客戶在分布式/微服務架構方面進行了一些嘗試與實踐,在這個過程中碰到了以前在單體應用下很少需要特意關注的問題。
比如數據一致性、比如stateless service、比如出現異常后的錯誤排查等等
在這個過程中,積累了一些經驗,我把這些經驗總結成范式(或者叫最佳實踐),一共八個,如上圖。
一、采用同步方式記錄業務流水
首先我們來看看第一范式:采用同步方式記錄業務流水
流水記錄了業務狀態最終確定前的整個過程,是給業務參與各方看的,這個參與各方包括了客戶(比如大家拿到的信用卡刷卡記錄)、第三方系統(比如對賬文件)、內部用戶(比如我們給客服打電話,客服可以知道你的交易歷史)等等。
由於流水的作用和系統日志非常像,因此有些系統在設計時會把這兩者混淆起來,基於性能的考慮,會像記錄日志那樣,用異步方式來記錄流水。其實這是非常大的誤區。就像上面所說,流水有業務含義,是給業務參與各方看的,它所記錄的數據應該是和業務數據有一致性要求,而日志是給我們程序員看的,偶爾丟個一兩條是可接受的。
因此我們需要用同步的方式來記錄業務流水,也就是說記錄流水應該和正常的業務操作在同一個事務中。
上圖中,第一個“內部操作”更改了業務數據狀態,因此需要同步記錄業務流水,其他幾個環節只記錄日志即可。
二、流水號設計的GAIR模式
在記錄流水和日志的過程中,我們需要唯一標識一筆服務調用。站在IT全局的視角來看,我們需要記錄並能在適當的時候還原整個調用鏈。出現數據不一致時,我們要進行補償操作,又需要能夠定位錯誤發生時的數據狀態……
這些都需要以“流水號”為基礎,這就帶來了微服務架構的第二個范式——流水號的GAIR(蓋爾)模式。
G、A、I、R分別代表:Global_ID(全局流水號)、Answer_ID(響應流水號)、InRequest_ID(外部請求流水號)、Request_ID(內部請求流水號)
這四個流水號的產生方、產生時機各不相同,下圖展示了它們之間的區別和聯系。
三、元數據驅動的微服務定義
第三個范式是“元數據驅動的微服務定義”
以元數據的方式定義微服務帶來兩個好處。
一、機器可讀,這給未來全面自動化提供了前提條件。
二、標准統一,這給服務在整個交付環節中的橫向打通提供了支撐。
我們在實踐中,以元數據方式,定義了服務接口數據的結構、每個數據項所遵循的數據標准、每個服務接收請求數據時的校驗規則和值轉換規則等等。
這些元數據提供給專門的服務治理系統、數據治理系統、DevOps平台,從而構建出數字化IT。
四、同步模式異步化
在移動互聯的外部環境中,微服務化的IT系統如何應對不確定的並發請求、超量請求?同時還要兼顧我們所連接的外部系統的網絡中斷、宕機等服務不可用、超時等一系列問題。
要解決這些問題,需要運用我們的第四個范式:以異步的方式處理同步調用。
在實踐中,我們所使用的異步方式和傳統異步不太一樣。
傳統基於事件的異步,每個並發流作為一個有限狀態機,應用直接控制並發,隨着負載的增加,吞吐量會飽和,響應時間也會線性增長。
我們使用SEDA(Staged Event Driven Architecture),將接入、接出與邏輯處理相隔離,根據不同的業務操作類型合理分組,分別對待。
關於SEDA的詳細介紹,請大家參看以前在群里的分享《為什么選擇SEDA作為雲平台的基礎消息處理架構》
五、進程間服務無狀態
接下來是第五個范式:進程間服務無狀態。
什么是狀態?首先,我們這里所說的狀態是一種數據。如果一個數據需要在多個服務之間共享才能完成一筆交易,那么這個數據就被稱為狀態。
依賴這個狀態的服務,就是有狀態服務。否則,就是無狀態服務。
在業務上,狀態的共享是不可避免的。典型的用戶Session、現在新出現的雲粘貼、網約車都是需要狀態在不同服務間共享的場景。
但在技術實現上,考慮到系統的可伸縮性,我們又需要做到無狀態化處理。
具體有四種手段:
一、請求方持有狀態,每次調用時傳遞給服務提供方
二、粘滯+復制,這種技術並不新鮮,傳統的JavaEE應用服務器集群就采用這種方式。這種方式對應用來說簡單有效,但需要中間件支持。
后面兩種手段類似,都可以稱為狀態共享
一種是,把狀態保存在分布式緩存中
另一種,把狀態保存在持久化數據庫中
區別也顯而易見,在此不做贅述。
具體使用哪種方式,要從多個維度綜合考量,這里列出了我們經常考量的幾個維度:時間窗口、性能、可靠性、安全性。
六、保證最終數據一致性
接下來是微服務架構下的數據一致性問題。這是一個大課題,概括的講,我們可能需要轉變思路,考慮采用柔性事務,使得數據達到最終一致。
當然,有些場景是必須要追求強一致性的,那么我們可能要在設計服務時就要考慮,是不是可以不分布。畢竟,“低耦合”是美好的,但同時還要有“高內聚”。
保證數據最終一致性有三種模式:
1、可靠事件模式
2、補償模式
3、TCC模式
關於這三種模式的詳細資料,以前在群里也做過分享《微服務架構下的數據一致性保證(一)》、《微服務架構下的數據一致性保證(二)》、《微服務架構下的數據一致性保證(三)》
七、用編排實現微服務組合
前面講了這些模式,從架構角度來看挺清楚,確實也應該這么做。但是從工程角度來看,實施起來難度其實也不小。微服務之間的調用超時、事務、異步、狀態等等,要做到代碼寫好,不出錯,恐怕也是一個門檻比較高的事情。
所以,我們強調:用編排方式實現微服務的組合。
無論是配置式的編排,還是圖形式的編排,都可以大大降低編程復雜度,使得一些很好的架構思想不會因為工程實現上的復雜和高門檻,而難以落地,最終成為空談。
如果大家對編排方式實現微服務的組合沒有直觀的感覺,推薦大家訪問:ifttt.com,一試便知。
八、業務配置集中管理
最后一個范式是:業務配置集中管理
記得前兩天有位群友問我,docker啟動時,如何根據不同的參數動態加載面向測試、生產環境的配置。
這個問題的答案就是業務配置集中管理。
其實技術上,業務配置集中管理沒有什么太多的難點。我們需要做的是有一個切實可行的步驟來逐步實現。
總結
今天講的內容,全部都來自於我們在客戶現場的實踐總結。有些經驗已經在產品中體現,有些經驗還沒有落到產品中去。希望能夠在今后的實踐和與大家的交流中,總結出更多的經驗,屆時一定會再次分享給大家。謝謝!
關於作者:
朱江,普元解決方案中心總經理
畢業於河海大學,2007年加入普元信息技術股份有限公司,長期致力於金融軟件平台建設實踐。主持完成多個金融行業平台產品及解決方案的研發工作,對金融行業技術架構有較深刻理解,曾主持中國工商銀行、建設銀行等多家大型企業的技術平台規划與落地,負責基於普元標准產品打造行業解決方案。
關於EAII
EAII(Enterprise Architecture Innovation Institute)企業架構創新研究院,致力於軟件架構創新與實踐,加速企業數字化轉型。
eaworld項目(微信號:eaworld,長按二維碼關注)
eaworld是EAII的官方微信賬號。