概述#

Service-based architecture 是 microservices 架構風格的一種混合體(hybrid),被認為是最務實的架構風格之一,主要歸功於其架構靈活性。雖然它屬於分散式架構(distributed architecture),但複雜度和成本不如 microservices 或 event-driven architecture,因此非常適合商業應用。

基本拓樸(Topology)#

基本拓樸是一個分散式的巨觀分層結構,由以下三個主要部分組成:

  • 獨立部署的使用者介面(User Interface)
  • 獨立部署的遠端粗粒度服務(coarse-grained domain services)
  • 單一資料庫(monolithic database)

服務通常被稱為 domain services,數量一般在 4 到 12 個之間,平均約 7 個。大多數情況下,每個 domain service 只有單一實例,但基於可擴展性、容錯或吞吐量需求,可以部署多個實例。

服務透過遠端存取協定(如 REST、messaging、RPC 或 SOAP)從使用者介面存取。大多數情況下,使用者介面直接透過嵌入的 service locator pattern、API gateway 或 proxy 存取服務。

Figure 13.1: Basic topology of the service-based architecture style

Service-based architecture 的一個重要特點是通常使用集中式共享資料庫。由於服務數量少(4-12 個),資料庫連線不會成為問題,且服務可以利用 SQL 查詢和 join,如同傳統的 monolithic layered architecture。

拓樸變體(Topology Variants)#

此架構風格存在許多拓樸變體,是最靈活的架構風格之一:

使用者介面變體#

  • 單一整體式 UI — 所有 domain service 共用一個使用者介面
  • 領域式 UI(Domain-Based)— UI 按領域拆分為多個介面
  • 服務式 UI(Service-Based)— 每個 domain service 各自擁有獨立 UI

Figure 13.2: User interface variants

資料庫變體#

  • 單一共享資料庫 — 所有服務共用一個資料庫
  • 領域分組資料庫 — 資料庫按領域分組(如兩三個資料庫)
  • 每服務獨立資料庫 — 類似 microservices,每個 domain service 各自擁有專屬資料庫

若選擇拆分資料庫,必須確保每個資料庫中的資料不被其他 domain service 所需。這可避免服務間的通訊(interservice communication)以及資料庫間的資料重複——在 service-based architecture 中應絕對避免 interservice communication。

API 層#

也可以在 UI 和服務之間加入 API layer(reverse proxy 或 gateway),適用於需要對外公開功能或整合跨領域關注點(如 metrics、security、auditing、service discovery)的場景。

Figure 13.4: Adding an API layer between the user interface and domain services

服務設計與粒度(Service Design and Granularity)#

由於 domain services 是粗粒度的,每個服務內部通常採用以下兩種設計方式之一:

  • 分層設計(Layered / Technical Partitioning)— API Facade Layer → Business Logic Layer → Persistence Layer
  • 領域設計(Domain Partitioning)— API Facade Layer 下以子領域(sub-domain)組織 component

無論哪種設計,每個 domain service 都必須包含某種 API access facade,負責接收並協調(orchestrate)來自 UI 的業務請求。

Figure 13.5: Domain service design variants

粗粒度 vs. 細粒度#

Service-based architecture 使用粗粒度的 domain services,因此可以使用 ACID 交易來確保資料庫完整性。相較之下,microservices 使用細粒度服務,通常需要依賴 BASE 交易(basic availability, soft state, eventual consistency),無法提供相同等級的資料一致性。

粗粒度服務帶來更好的資料完整性與一致性,但代價是:對 OrderService 中下單功能的變更需要測試整個服務(包括付款處理),且部署時有更多程式碼承受風險。

資料庫分區(Database Partitioning)#

當所有服務共享單一資料庫時,table schema 變更可能影響所有服務。有兩種管理方式:

單一共享函式庫(不推薦)#

  • 所有 domain service 使用同一個包含所有 entity objects 的 shared library(如 JAR 或 DLL)
  • 任何 table 變更都會影響所有服務,需全部重新部署
  • 難以判斷哪些服務真正受到變更影響

Figure 13.6: Using a single shared library for database entity objects

聯合共享函式庫(推薦)#

  • 將資料庫邏輯分區為不同的領域(如 common、customer、invoicing、order、tracking)
  • 每個領域對應一個專屬的 shared library
  • 變更只影響使用該 library 的服務

資料庫的邏輯分區應盡可能細粒度,同時維持明確的資料領域定義,以更好地控制 service-based architecture 中的資料庫變更。

注意 common 領域和對應的 common_entities_lib 是所有服務共用的。這些共用 table 的變更需要所有服務的協調。可以透過版本控制鎖定 common entity objects,限制只有資料庫團隊可以修改。

範例架構#

以電子回收系統(Electronic Recycling System)為例,涵蓋以下流程:quoting(報價)→ receiving(收件)→ assessment(評估)→ accounting(付款)→ item status(狀態查詢)→ recycling(回收)→ reporting(報表)。

此系統的架構特色:

  • 每個領域實作為獨立部署的 domain service
  • 只有高流量服務(Quoting、ItemStatus)需要擴展,其他服務只需單一實例
  • UI 按領域聯合為三個部分:Customer Facing、Receiving、Recycling and Accounting
  • 兩個獨立資料庫:外部客戶面向與內部作業,以不同的網路區域分隔,提供安全性保護

Figure 13.8: Electronics recycling example using service-based architecture

架構特性評分(Architecture Characteristics Ratings)#

架構特性評分
Partitioning typeDomain
Number of quanta1 to many
Deployability★★★★
Elasticity★★
Evolutionary★★★
Fault tolerance★★★★
Modularity★★★★
Overall cost★★★★
Performance★★★
Reliability★★★★
Scalability★★★
Simplicity★★★
Testability★★★★

Figure 13.9: Service-based architecture characteristics ratings

評分解析#

  • Deployability / Testability / Modularity(4 星) — 將應用拆分為獨立部署的 domain services 帶來更快的變更速度(agility)、更好的測試覆蓋率和更頻繁的部署
  • Fault tolerance(4 星) — 服務通常是自包含的,不依賴 interservice communication;若某個服務當機,不影響其他服務
  • Scalability / Elasticity(3 星 / 2 星) — 粗粒度服務使擴展時複製更多功能,不如 microservices 高效
  • Overall cost / Simplicity(4 星 / 3 星) — 是最容易且成本效益最高的分散式架構之一
  • Reliability(4 星) — 粗粒度服務意味著更少的網路流量、更少的分散式交易、更少的頻寬使用

Figure 13.10: Separate quanta in a service-based architecture

適用場景(When to Use)#

  • 務實的分散式架構 — 需要分散式架構的優勢,但不需要 microservices 或 event-driven 的完整威力
  • Domain-driven design — 粗粒度且領域範疇的服務自然對應 DDD 的 bounded context
  • ACID 交易需求 — 大多數交易可以限定在單一 domain service 內,保留傳統的 commit 和 rollback 功能
  • 避免粒度複雜性 — 不想陷入 microservices 細粒度帶來的 orchestration 和 choreography 問題
  • Orchestration(透過 mediator 協調多個服務)和 Choreography(服務之間直接對話)在服務越細粒度時越必要,但 service-based architecture 的粗粒度服務大幅降低了這類需求