單體到微服務架構的涅槃重生之路?

智在碧得發表於2024-05-08

在技術演進的歷史長河中,單體架構曾是眾多專案的起點,但隨著業務需求日益複雜,微服務架構憑藉其靈活性和可擴充套件性逐漸成為新寵。行業內對此有著激烈的討論,尤其是網際網路大廠和行業技術大佬們對微服務架構的看法頗具影響力。

亞馬遜的CTO Werner Vogels就曾強調過微服務架構對企業快速迭代的重要性,他認為,構建小型、鬆散耦合的服務能夠提高系統的可靠性和效率。谷歌也傾向於使用微服務架構,這對於他們快速部署新功能和實現全球規模的服務至關重要。

此外,技術界的權威如Martin Fowler也對微服務架構持肯定態度,他在多篇文章中詳細闡述了微服務架構的優勢和實施策略,強調了它在現代軟體開發中的適用性。

這些討論讓企業更清楚地認識到,微服務架構能顯著增強系統穩定和併發處理能力。儘管存在服務治理和分散式事務等挑戰,但網際網路大廠的成功案例和技術大佬們的深入分析,都為其他企業轉型微服務架構提供了寶貴的經驗和信心。

當然,單體架構與微服務架構的辯論不止觸及技術的表層,更關乎對未來業務模式和運營效率的深遠考量。對於企業而言,選擇適合自己的架構,才是重要的。

1 單體架構與微服務架構

1.1 什麼是單體架構

單體架構(Monolithic Architecture)是一種將所有功能打包在一個容器中一起執行的一種架構,一個例項中整合了一個系統的所有功能。透過負載均衡軟體/裝置實現多例項呼叫。

1、優點

部署簡單:由於是完整的結構體,可以直接部署在一個伺服器上;

程式碼統一:組建密集整合,原始碼通用,程式碼組織一致;

研發成本低:單一服務和業務聚合,減少人力成本;

技術簡單:只需要知道簡單的技術棧,即可研發。

2、缺點

維護困難:隨著業務量的增加,服務逐步複雜,由於元件高度耦合,開發人員實現業務功能的同時大機率會影響到其它功能;

系統啟動慢:業務多、程式碼模組多,啟動週期漫長;

伸縮性差:不能針對業務模組單獨擴容,需要對整體服務進行擴容;

故障風險大:單體服務的某個元件出現問題,會導致整個服務不能用;

技術棧僵化:隨著新技術迭代出現,單體服務技術風險更大。技術僵化在原地,時間越長,技術漏洞將越來越難以修復。

1.2 什麼是微服務架構

微服務架構是一種架構概念,它強調將應用程式的功能分解為多個小的服務,這些服務可以獨立開發、管理和部署,每個服務執行在自己的程序中,並透過輕量級的通訊機制如REST API進行互動。微服務架構的核心在於解耦,它透過減少服務之間的依賴和耦合,提高了系統的靈活性和可擴充套件性。

1、優點

業務容易實現:服務職責單一,業務邏輯單一,程式碼量少,便於程式碼管理和迭代開發;

服務獨立:每個服務都採用獨立的技術棧進行開發,使得部署更新可以針對單個服務進行,從而降低整體風險並提高系統的靈活性和可維護性;

可擴充套件性:微服務架構允許根據業務需求靈活地增減資源應對負載變化。單個應用變更時,只需要重新部署,保持服務顆粒度隔離,即可確保系統即使發生區域性故障也可繼續執行;

技術棧靈活:每個服務可以有獨立的技術棧,每個服務都可以獨立更新對應的技術棧,從而不斷升級技術棧提高服務質量。

2、缺點

複雜度增加:微服務架構可將一個系統拆分為多個獨立的服務,這增加了額外的複雜度。例如,需管理分散式資料的一致性,且需處理服務間的通訊問題;

成本高:服務越多,運維要求越高,投入資源越多,成本越高。

透過上述內容,我們對單體架構和微服務架構的概念及兩者之間的差異有了一個整體的瞭解。接下來,我們將探討如何在實際專案實踐中將單體專案拆分為微服務架構。

2 充電樁拆分前專案剖析

我們已經掌握了單體架構與微服務架構的差異,接下來我們將在最新的充電樁專案中實際操作,將傳統的單體應用進行拆分,實施微服務架構。

在開始一個專案時,首先需要對專案進行定位,明確其架構型別,並評估其是否能夠支援高併發、高效能和高可用性,同時考慮它是否能適應未來的業務發展需求。

充電樁專案是一個外採專案,它是一個十分典型的單體專案,服務有狀態而且手動單機部署,且服務不能高併發、高可用與高效能。現有架構只能滿足當時的現有裝置,在未來10倍業務量倍增下,現有的架構明顯不能滿足這些需求。

為了應對未來三年10倍業務量倍增的挑戰,並確保服務的高併發、高效能和高可用性,微服務的可擴充套件性高、服務高獨立、職責單一,並且技術棧靈活,便於升級與維護。因此,微服務架構成為了首選。

在選擇未來架構後,首先需要考慮從單體架構遷移到微服務架構過程中可能遇到的以下障礙:

技術棧較老舊:無法更新到最新技術棧,無法適配spring cloud/雲原生微服務架構;

服務有狀態:服務訪問負載固定IP Hash訪問指定一臺機器,可以用性十分差;

前後端不分離:前端程式碼和後端程式碼緊密耦合,不易重用。頁面響應慢,使用者體驗差,不易維護;

可維護性差:程式碼耦合模組,修改一個模組會導致其他模組發生意想不到的變化,從而增加了維護成本;

可擴充套件性差:模組之間過於依賴,不容易擴充套件功能;

可重用性差:高耦合的模組不容易在其他系統中重用;

可測試性差:測試一個模組需要依賴其他模組,增加測試難度;

部署架構不靈活:需要手動部署,停機時間長,且可用性差。

要實現充電樁專案微服務化,就必須解決以上阻礙。

3 充電樁拆分微服務架構步驟

3.1 單體服務實現無狀態

單體服務實現無狀態

我們為什麼要將服務去狀態?服務有狀態對系統會造成哪些影響?我們先來分析一下服務有狀態有哪些缺點:

1、狀態管理問題:每個服務例項可能需要維護自己的狀態,這會導致大量的記憶體佔用和管理成本;

2、擴充套件性問題:有狀態服務不易於進行水平擴充套件,因為擴充套件例項時,它們將失去之前的狀態,並且需要合理地管理狀態遷移;

3、高可用性問題:如果服務例項失敗,有狀態服務可能需要額外的機制來保證狀態的高可用性;

4、資料一致性問題:在分散式系統中,多個例項同時訪問和修改同一狀態時,可能會出現資料一致性問題;

5、效能問題:有狀態服務可能需要更多資源來處理本地的狀態,這可能會影響效能。

從上述單體服務有狀態缺陷性分析,我們可以看出,服務有狀態是實現服務高併發、高效能和高可用目標的障礙。因此,接下來,我們將重點探討服務無狀態的分析和設計。

3.2 充電樁單體服務有狀態架構圖

當使用者A的IP固定雜湊到主機A後,那麼它後面的流量都會一直流向主機A,而不會流向主機B。使用者A的所有請求校驗資訊都儲存在session中,使用者B同理。這樣一來,如果有某臺伺服器發生故障,那麼所有依賴該伺服器的使用者都會無法訪問資源,降低了系統的可用性。具體見下圖所示:

與服務有狀態相比,服務無狀態的主要優勢在於它們能夠輕鬆地實現高可伸縮性和高可用性。無狀態服務不需要儲存會話狀態,因此不會成為系統的瓶頸。當請求分佈在多個無狀態服務例項之間時,每個例項只需處理它接收到的請求,不需要共享任何內部狀態。

3.3 無狀態實現步驟

無狀態是指一個系統或者元件不儲存關於先前互動的資訊或者狀態。

微服務架構設計中的一個核心原則就是服務無狀態化。微服務處理每個請求時不會依賴於會話資訊或者狀態,無需考慮之前的互動邏輯。服務無狀態的目的是簡化請求處理、服務部署、服務伸縮、服務容錯、資源最佳化或者服務狀態恢復和同步等。

如何實現無狀態?其實現步驟如下:

1、狀態分離:將狀態從服務中分離出來,並將其儲存在外部系統中,如資料庫或分散式快取,服務脫離狀態管理。

2、網路請求管理狀態:透過請求(API請求引數、http請求頭及cookie等)傳遞狀態資訊,以保證請求執行所需要的引數。

3、使用訊息佇列:將請求封裝到訊息佇列,透過訊息佇列通訊實現服務無狀態化。

綜合來說,服務無狀態化是實現高可用、可伸縮和易於管理的分散式系統的關鍵因素。

3.4 充電樁單體服務無狀態架構圖

在無狀態時,使用者A和使用者B可以正常地透過Webview進行訪問。由於系統設計中包括對兩臺輪伺服器的輪詢機制,即使其中一臺伺服器出現故障,請求可以被另一臺伺服器處理,保障了系統的正常執行和高可用性。具體見下圖所示:

3.5 電樁單體服務前後端分離無狀態架構圖

在無狀態實現完成後,可以逐步將JSP頁面遷移到Vue前端服務中,並透過Nginx實現轉發。具體見下圖所示:

3.6 充電樁微服務前後端完全分離態架構圖

4 充電樁專案實踐拆分

4.1 單體架構充電樁專案架構

從上圖的架構圖可以看出,所有的服務都依賴於center服務。center是一個功能混雜的服務,沒有具體的功能劃分。一旦center服務故障,將導致整個服務無法正常工作。

4.2 單體架構拆分步驟

斷開gateway tcp和gateway ssl對center的直接依賴,所有的呼叫應該透過MQ來實現。

center主要提供三個功能:小程式訪問功能、主營資料消費功能及裝置消費的功能。為了提高系統效能和降低故障分析,可以將center功能拆分為主資料kafka消費、裝置服務與小程式服務這三個模組。

將webview管理系統單獨拆分為微服務,解除其對center的依賴。

將frontview管理系統單獨拆分為微服務,解除其對center的依賴。

我們從單體架構開始,逐步將其核心功能模組轉化為微服務架構。具體而言,是在保留center的三大功能——小程式訪問、主營資料消費以及裝置消費功能的基礎上,我們將閘道器、webview和frontview從對center的依賴中解耦,使它們演變為獨立的微服務架構。

透過這種轉變,center避免了直接處理服務呼叫,實現了與其他服務的完全分離。這導致center不再直接管理流量的進出,從而顯著減少了系統的複雜性及可能的故障源,增強了系統的維護性和可靠性。

4.3 微服務架構領域劃分

在拆分服務邊界和職責之前,通常會設定一些基礎服務,包括使用者服務、工單服務、訂單服務、支付服務、任務排程服務、裝置服務及資料匯流排消費微服。基於這些基礎服務,我們進一步定義了上層服務,如公眾號服務、小程式服務與後臺管理系統服務等。最後,為了支援第三方業務整合,我們還提供了第三方業務支撐服務,以實現與外部系統的無縫對接和資料交換。


5 總結

在將單體架構拆分成微服務架構的過程中,我們從這兩種架構的基本概念出發,詳盡探討了拆分過程中可能遇到的障礙及具體的拆分步驟,並分享了充電樁專案實踐經驗。對此,我們總結出以下關鍵點:

將單體架構拆分成微服務架構的核心是服務無狀態、前後端逐步分離和流量切分;

解耦單體服務到職責單一的多元服務是服務“三高”(高併發、高效能和高可用)可用的關鍵;

技術棧的不斷迭代升級是維持微服務架構活力的血液,分散式資料管理和監控是維持微服務架構監控的保障,而統一規範的RPC通訊協議則是微服務排程通訊的質量基準。

——————————————————————————————————————————————————————————

本文作者:
王志堅:碧桂園服務JAVA開發專家

指導人:
毛卓:碧桂園服務技術總監
劉剛:碧桂園服務架構師

相關文章