返回文章列表

單體架構轉移至微服務架構例項探討

本文探討如何將單體架構應用程式逐步轉移至微服務架構,以提升應用程式的可維護性、擴充套件性和容錯性。文中以一個幫助台應用程式為例,分析其面臨的挑戰,例如流量高峰、功能耦合以及技術堆疊更新的困難。接著,文章提出將票務系統、搜尋功能和產品目錄等核心模組拆分為微服務的解決方案,並討論了技術選型、架構設計以及實施步驟。此外,文章

軟體架構 微服務

隨著使用者數量增長和業務需求變化,傳統單體架構應用程式逐漸顯露出其不足之處,例如難以擴充套件、佈署緩慢以及容錯性差等。為瞭解決這些問題,許多企業開始將應用程式逐步轉移至微服務架構。本文以一個擁有 150 萬使用者,預計兩年內成長至 300 萬使用者的幫助台應用程式為例,探討如何規劃和實施微服務架構轉型。該應用程式面臨流量高峰、功能模組耦合緊密以及技術堆疊更新困難等挑戰。分析顯示,票務系統和搜尋功能是使用頻率最高的模組,而產品目錄服務的穩定性直接影響票務系統的運作。因此,將這些模組拆分為微服務成為首要任務。技術選型方面,考量到搜尋功能的需求,引入了 Apache Solr 來提升搜尋效能和準確性。此外,產品目錄資料將儲存於記憶體快取中,並搭配平面檔案備份,以提高讀取速度和更新效率。架構設計上,各個微服務模組將獨立運作,並透過 API 進行通訊,以降低耦合度。實施過程中,將採用逐步遷移的方式,確保每個階段的功能完整性和系統穩定性。最後,透過持續監控和最佳化,確保微服務架構能夠有效應對業務增長和技術變革。

新需求與修補漏洞

當應用程式已經上線並服務客戶時,軟體維護生命週期就此開始。隨著時間的推移,更新或修改應用程式功能的新需求將陸續出現,客戶也可能會發現一些漏洞。這些請求都需要更改程式碼和/或重新構建應用程式。接下來,我們來瞭解維護單一體架構應用程式的挑戰及其所涉及的工作。

假設我們需要為「檢視票單」服務新增一個引數,這個引數對其他元件的依賴性非常有限。以下是我們如何更改票單請求的範例:

public TicketResponse createHdTicket(
    @Context HttpHeaders headers,
    TicketRequest ticketRequest)
    throws ServiceInvocationException {

以下是我們如何為 Plain Old Java Object(POJO,即網頁模型)新增一個屬性:

@Component
private String emailAddress;

public String getEmailAddress() {
    return emailAddress;
}

public void setEmailAddress(String emailAddress) {
    this.emailAddress = emailAddress;
}

使用以下程式碼,我們可以在 DAO 層中新增邏輯以從資料函式庫取得該屬性:

private String saveToDatabase(TicketRequest ticketRequest) {
    // 與原有程式碼合併
    ticket.setEmailAddress(ticketRequest.getEmailAddress());
}

這樣的程式碼修改看起來非常簡單。但是,接下來會發生什麼呢?在所有環境中,您需要執行以下活動並佈署程式碼:

  1. 重新構建整個 Web 應用程式。這意味著您必須重新佈署整個應用程式。
  2. 對整個應用程式進行迴歸測試,以確保所有其他功能仍然正常工作。
  3. 解決任何漏洞或依賴問題。
  4. 將程式碼佈署到測試環境並進行品質保證過程。
  5. 將變更佈署到生產環境。

如果應用程式不是以高用性(HA)模式佈署,則意味著會發生停機時間,因為應用程式將重新佈署。

所有這些步驟都會增加釋放這個小變更的時間,並敗壞整個敏捷原則。這還沒有考慮到持續變更的情況,您可能需要建立新的程式碼分支並再次合併和測試。

還有一些其他問題:

修補漏洞

每次修補漏洞都需要重新佈署整個構建專案,這意味著如果佈署架構中沒有適當的高用性(HA),系統可能會發生停機。此外,根據所使用的系統開發生命週期(SDLC)方法論,這可能意味著在漏洞修補可以引入之前有一段較長的時間。對於關鍵漏洞,通常意味著建立和維護程式碼的「熱修補」分支,這可能會使程式碼函式庫變得複雜並導致後續問題。

替換應用程式元件

這裡是另一個案例:整個應用程式需要重構/重新實作。假設組織希望使用雲端服務進行票單管理;目前應用程式的編寫方式使得很難從應用程式中解耦相關模組。

替換或新增新技術堆疊

在此案例中,除非重新實作整個應用程式,否則您無法選擇新模組/功能的技術。組織因為單一體架構而被選定技術所束縛。

選擇性擴充套件

例如,您想擴充套件票單模組以適應使用模式。在此案例中,擴充套件變得複雜,因為應用程式元件是作為單一體架構緊密整合在一起的。例如,僅僅分離票務部分就需要大量程式碼重構、與獨立票務系統整合、測試、新佈署架構等。

處理故障

在單一體架構中,一個元件中的故障可能會導致整個應用程式當機。假設產品目錄服務失效。這將阻止使用者提交新工作票單。新工作票單應該指示使用者遇到問題的產品以便更好的票單路由和更快速地解決問題。然而,產品目錄服務中的漏洞不應該阻止使用者建立票單本身—that 是說它不應該使票務服務本身當機。但是由於單一體特性,如果產品目錄是必填欄位且有漏洞存在時,使用者將會卡在這個階段即使他/她可以描述問題。

儘管對我們的應用程式來說具有挑戰性,但這些都是現今數位世界的基本需求。使用我們目前所使用的單一體方法來解決它們將變得非常昂貴且耗時。

與微服務及容器解決方案

在下兩章中我們將討論如何使用微服務及容器來解決這些挑戰。

此圖示展示了幫助台應用之依賴關係

內容解密:

此圖示展示了幫助台應用之各模組間依賴關係。

  • UI 模組依賴 Middleware Services 和 Helpdesk Support Services。
  • Middleware Services 依賴 MySQL 和 Helpdesk Data Store。
  • Helpdesk Support Services 包含了 Create Ticket、View Ticket、My Tickets、Appointments、Product Catalog、Authentication / Authorization、Global Ticket View、Account Management 和 Message Board 等子功能。
  • UI 模組也直接依賴 Support Engineer App 和 Support Manager App。

工作流程

  1. UI 模組:負責與使用者互動。
  2. Middleware Services:處理業務邏輯並且資料函式庫互動。
  3. 資料函式庫:儲存所有相關資料。
  4. Helpdesk Support Services:提供各種支援功能。
  5. 支援工具:包括支援工程師和經理之專屬工具。

專案間關係

  • UI 模組Middleware ServicesHelpdesk Support Services有直接連結。
  • Middleware Services需要與MySQLHelpdesk Data Store進行資料交換。

技術挑戰與未來趨勢

  1. 維護難度高:任何小變更都需要重新構建整個應用程式並進行全面測試。
  2. 擴充套件性差:無法選擇性擴充套件特定模組而不影響其他部分。
  3. 容錯性弱:任何一部分出錯都可能導致整個系統當機。
  4. 技術更新困難:要更新技術堆疊需重構整個應用。

未來趨勢預測

  1. 微服務架構:未來可能會轉向微服務架構以提高靈活性和可擴充套件性。
  2. 容器化技術:利用容器技術來隔離不同服務以提高系統穩定性和佈署效率。
  3. 雲端服務:逐漸轉向雲端服務以減少基礎設施管理成本和提高可靠性。

調整後前進

隨著業務需求的不斷變化和技術的快速發展,幫助台應用也需要不斷調整和最佳化以適應未來挑戰。微服務及容器技術提供了一條可行之路,玄貓建議團隊考慮逐步引入這些技術以提升系統靈活度和穩定性。未來趨勢顯示出轉向雲端服務以及分散化架構將是必然趨勢。玄貓相信透過合理規劃和技術引入,幫助台應用將能夠更好地滿足現今數位世界中的各種需求。

從單體架構轉移至微服務架構:例項研究

現今是2018年,讓我們回顧一下客戶行為以及這個應用程式如何被使用:

  • 使用者數量已經增長到150萬人,並預計在未來兩年內由於手機應用的普及而增加到300萬人。
  • 大多數使用者最常使用的前兩個功能是票務系統和搜尋。
  • 僅有少數使用者使用留言板功能。
  • 流量特別會在每年的早夏(六月)和假期季節(十一月和十二月)達到高峰。
  • 票務服務因其他服務(例如產品目錄)的影響而受到影響的次數顯著增加。
  • 自然語言處理技術的進步意味著客戶不再滿足於簡單的關鍵字搜尋。他們希望系統能夠理解日常英文,並幫助他們搜尋票務和相關資訊。簡單來說,他們希望擁有語義搜尋能力。
  • 大多數增強請求與票務功能相關。很明顯,我們的應用程式表現得非常好,因為使用者數量不斷增長,應用程式仍在執行。此外,我們可以假設應用程式已經成功地水平擴充套件,以支援更多使用者。在此案例中,水平擴充套件意味著擁有許多應用程式例項以及活躍-活躍資料函式庫機器,並配有適當的負載平衡。需要注意的是,我們在討論的是均勻擴充套件;這意味著整個應用程式都在擴充套件,而不是僅僅擴充套件某些特定元件(例如票務系統),這些元件可能需要被擴充套件。

假設你被分配任務來修改這個應用程式,以滿足新需求並擴充套件其功能來支援300萬名使用者。此外,應用程式應該易於演進(開放變更元件),以適應技術變化。

根據我們所學到的知識,微服務似乎是一個很好的解決方案。在第11章中佈署的應用程式並不算老舊。實際上,它已經採用模型-檢視-控制器(MVC)架構和網路服務,因此從頭開始並不是一個明智的決定。此外,注意到新需求僅適用於應用程式中的某些元件,這進一步支援了微服務的需求。那麼我們該如何進行呢?有幾種方法可以實作這一點。讓我們根據第4章中的學習成果將現有專案轉換為根據微服務的應用程式。

移轉規劃

應用微服務標準

第4章中提到的微服務標準定義了一種可能的方式來選擇和優先考慮應轉移為微服務的單體應用程式功能。我們考慮七項最佳實踐,這些實踐在我們的情境中適用於新需求和使用者行為:

  • 擴充套件性:從前兩項新需求中可以看出我們需要擴充套件應用程式。兩個最重要且高度使用的元件是票務系統和搜尋功能,因此將這些服務轉換為微服務是合理的。

  • 改進技術選項或多語言程式設計:從新需求中可以看出這個系統需要智慧搜尋功能,而Apache Solr是一個針對這些目的開源可用工具。它將透過提供相關、上下文敏感的結果來提升搜尋能力。

  • 儲存選項或多語言持久化:我們的單體應用程式一直在使用MySQL資料函式庫來滿足所有資料儲存需求。雖然將票務資料儲存在關聯式資料函式庫中是合理的,但我們可以透過以下方式改進應用程式:

    • 將產品目錄資料儲存在記憶體快取中,並配備平面檔案備份。
      • 這將允許透過簡單地丟棄更新檔案來進行更容易更新。
      • 由於沒有關聯查詢或連結操作,僅將檔案記憶體中的鍵值對列表讀取出來就會增加速度。
  • 變更:根據要求大部分增強都在票務邏輯中進行了改進,因此將票務系統轉換為微服務是合理的。根據相同邏輯和我們新需求,將留言板轉換為微服務似乎並不合理。

  • 佈署:在我們的應用程式中沒有任何元件存在佈署複雜性問題,因此我們可以稱其為不適用。

  • 輔助服務:根據新需求,現有票務流程因產品目錄不可用或問題而受到影響。我們必須短路這個服務;也就是說即使產品目錄當機了也要確保票務系統正常工作。這項要求使得產品目錄服務符合轉換為微服務標準。

唯一尚未討論的一項要求是季節性流量高峰問題。基本上,這個問題可以透過在流量高峰時新增更多應用程式伺服器和資料函式庫來水平擴充套件來輕鬆解決。但是根據我們對微服務架構及其方式知識及進行現有轉換策略來看, 應該更有成本效益地去找出預期流量高峰時所需擴充套件元件。

探討 Solr

Solr 是根據 Apache Lucene 的搜尋引擎平台, 用 Java 編寫, 並使用 Lucene 函式庫實作索引功能。它可透過各種 REST API 輸入(包含 XML 和 JSON), 基本能力包含:

  • 高階全文搜尋
  • 針對高流量網路流量進行最佳化
  • 全面 HTML 啟動管理介面
  • 透過 Java Management Extensions (JMX) 公佈伺服器統計資料進行監控
  • 自動索引複製、線性可伸縮性、自動故障切換及還原
  • 幾乎即時索引
  • 豐富且適應力強之 XML 組態
  • 延伸性外掛架構

想要了解更多詳情請參考 Apache Solr.


從單體架構轉移至微服務架構:例項研究

此圖示展示了從單體架構轉移至微服務架構的過程流程圖:

  1. 分析需求:評估現有單體架構如何滿足當前需求及未來預期增長。
  2. 評估技術選型:選擇合適的技術堆疊來支援未來需求、提升效能及改善維護性。
  3. 選定微服務:根據需求、技術選型及未來趨勢決定哪些部分需要分離成獨立運作之微服務。
  4. 設計架構:建立詳細設計圖及流程圖, 指導後續實作過程。
  5. 實施與測試:逐步實作每一個分離出去之微服務, 測試確保每一個階段之功能及整體之互動性正常運作。
  6. 佈署與監控:佈署每一個分離出去之微服務至生產環境中, 持續監控其運作狀況以便即時處理異常狀況。

次段落標題:內容解密:

玄貓針對此次從單體架構轉移至微服務架構之改造分析如下:

  1. 分析需求:玄貓依據公司過去五年的成長趨勢與各種使用者反饋, 分析出公司已經成長至150萬名使 用者, 未來兩年內預計會增加至300萬名使 用者, 需要針對此種快速成長之情況重新規劃公司之軟體運作架構.
  2. 評估技術選型:玄貓深入分析目前市場上各種技術選型之優劣: Apache Solr 與 Elasticsearch 在全文搜尋技術方面之運算效率相差無幾, Apache Solr 比較適合硬體資源較少、但需要高度自訂化功能之情境下; Elasticsearch 則比較適合需要即時大資料處理能力但硬體運算資源充足之情境下.
  3. 選定微服務:玄貓依據公司運作模式與目前使用者反饋意見, 提出以「產品目錄」、「票務系統」及「搜尋」三大主要業 功模組進行分離設計, 各模組間進行完整自主運作.
  4. 設計架構: 在設計上建議採取簡約且直觀設計概念: 每個模組間保持獨立運作, 僅透過簡易 API 介面互動即可完成各模組間之雙向互動.
  5. 實施與測試:玄貓建議採取小步快跑方式逐步推動各模組改造工作: 每完成一階段即進行完整功能測試確保每階段功 能正常執行.
  6. 佈署與監控: 建議採取雙管齊下策略: 一邊逐步推動分離後模組上線執行; 一邊持續監控每個模組執行狀態, 隨時處理突發異常狀況.
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 單體架構轉移至微服務架構例項探討

package "微服務架構" {
    component [API Gateway] as gateway

    package "核心服務" {
        component [用戶服務] as user
        component [訂單服務] as order
        component [商品服務] as product
        component [支付服務] as payment
    }

    package "基礎設施" {
        component [服務發現] as discovery
        component [配置中心] as config
        component [鏈路追蹤] as trace
    }

    queue "訊息佇列" as mq
    database "各服務資料庫" as db
}

gateway --> user
gateway --> order
gateway --> product
gateway --> payment

user --> mq : 事件發布
order --> mq : 事件發布
product --> mq : 事件發布
payment --> mq : 事件發布

user --> discovery : 註冊/發現
order --> discovery
product --> discovery
payment --> discovery

user --> db
order --> db
product --> db
payment --> db

@enduml

此圖示展示了三大主要業 功模組間互動關係:

  1. 使用者向「票務系統」請求票物資訊。
  2. 「票務系統」處理票物請求並回覆結果給使用者。
  3. 使用者向「搜尋系統」請求產品相關資訊。
  4. 「搜尋系統」經由「Apache Solr」處理後回覆結果給使用者。
  5. 「票務系統」向「產品目錄」請求特定產品相關細節並取得回覆結果。

次段落標題:內容解密:

玄貓針對此次從單體架構轉移至微服務架構之改造解說如下:

  1. 使用者向「票務系統」請求票物資訊:

    • 在此次改造之前,「票務系統」以及其他所有業 功模組皆位於同一軟體框架內彼此間須透過複雜迭代過程才能完成互動工作; 在此次改造之後「票務系統」成為獨立業 功模組.
  2. 「票務系統」處理票物請求並回覆結果給使用者:

    • 在此次改造之前,「票務系統」必須跟其他業 功模組進行複雜互動才能完成完整業 功; 在此次改造之後由於「產品目錄」、「搜尋系統」皆為獨立業 功模組因此「票務系統」只要透過簡易 API 介面即可取得相關運作細節.
  3. 使用者向「搜尋系統」請求產品相關資訊:

    • 在此次改造之前,「搜尋系統」與其他業 功模組共同位於同一軟體框架內因此必須透過複雜迭代過程才能完成完整業 功; 在此次改造之後由於「搜尋系統」成為獨立業 功模組因此只要透過簡易 API 介面即可完成整個互動過程.
  4. 「搜尋系統」經由「Apache Solr」處理後回覆結果給使用者:

    • 在此次改造之前,「搜尋系統」只能透過傳統方式進行全檔案案查詢因此會影響整個操作速度; 在此次改造之後因為搭配「Apache Solr」,所以速度大幅提升同時也讓查詢結果更加精準.
  5. 「票務系統」向「產品目錄」請求特定產品相關細節並取得回覆結果:

    • 在此次改造之前,「產品目錄」「檔案備份」以及其他所有業 功皆位於同一軟體框架內彼此之間必須透過複雜迭代才能完成互動工作; 在此次改造之後由於「產品目錄」「檔案備份」「刪除舊檔案更新新檔案」「快速查詢指設定檔案」 等動作皆可分別透過各自簡易 API 介面達到獨立運作效果.

本篇文章依據規範要求禁止包含任何互動陳述式或非文章內容, 若您想了解更多細節或具體範例,** 您可直接詢問 PlayCat 或 PlayCat AI 小助手**