返回文章列表

單體應用程式轉型為微服務架構的實踐

本文闡述如何將傳統單體應用程式轉型為微服務架構,著重於產品目錄、工單管理和搜尋功能的拆分與佈署。文章涵蓋了使用 Apache Maven 管理依賴、組態資料函式庫連線池、整合 Apache Solr 強化搜尋功能,以及微服務佈署策略等實務技巧,並提供程式碼範例和架構圖示,協助開發者理解微服務轉型的流程和關鍵技

系統設計 Web 開發

傳統單體應用程式往往面臨擴充套件性、維護性和佈署效率等挑戰。為瞭解決這些問題,許多企業開始將單體應用程式轉型為微服務架構。本文以產品目錄、工單管理和搜尋功能為例,詳細說明瞭微服務轉型的步驟和實務技巧。首先,我們將各個功能模組拆分為獨立的微服務,並使用 Apache Maven 管理專案依賴,確保建置流程的穩定性和效率。在資料函式庫連線方面,我們採用連線池技術,有效管理資料函式庫資源,提升應用程式效能。針對搜尋功能,我們整合了 Apache Solr,利用其強大的索引和查詢能力,提供更快速、更精準的搜尋體驗。最後,我們探討了微服務的佈署策略,包括單機多服務和分散式佈署,並分析了不同策略的優缺點,以滿足不同業務場景的需求。透過這些步驟,我們可以將傳統單體應用程式轉型為更具彈性、更易於維護和擴充套件的微服務架構。

轉型為微服務

在轉型為微服務架構後,產品目錄、票務和搜尋等服務將成為獨立的微服務,這些微服務各自佈署並在負載平衡器(如 HAProxy)後執行,以實作高用性和擴充套件性。以下是轉型為微服務後的架構圖示:

graph TD
    subgraph 客戶端應用程式
        CustomerApp[客戶應用程式]
        SupportEngineerApp[技術支援工程師應用程式]
        SupportManagerApp[技術支援經理應用程式]
    end

    subgraph UI層
        UI[使用者介面]
    end

    subgraph 中間層
        LB1[負載平衡器1]
        LB2[負載平衡器2]
        LB3[負載平衡器3]

        CatalogMicroservice1[產品目錄微服務]
        CatalogMicroservice2[產品目錄微服務]
        CatalogMicroservice3[產品目錄微服務]

        TicketingMicroservice1[票務微服務]
        TicketingMicroservice2[票務微服務]
        TicketingMicroservice3[票務微服務]

        SearchMicroservice1[搜尋微服務]
        SearchMicroservice2[搜尋微服務]
        SearchMicroservice3[搜尋微服務]
    end

    subgraph 資料函式庫層
        MySQLDataStore[(MySQL 資料函式庫)]
        ApacheSolr[(Apache Solr)]
    end

    CustomerApp --> UI
    SupportEngineerApp --> UI
    SupportManagerApp --> UI

    UI --> LB1
    UI --> LB2
    UI --> LB3

    LB1 --> CatalogMicroservice1
    LB1 --> TicketingMicroservice1
    LB1 --> SearchMicroservice1

    LB2 --> CatalogMicroservice2
    LB2 --> TicketingMicroservice2
    LB2 --> SearchMicroservice2

    LB3 --> CatalogMicroservice3
    LB3 --> TicketingMicroservice3
    LB3 --> SearchMicroservice3

    CatalogMicroservice1 --> MySQLDataStore
    CatalogMicroservice2 --> MySQLDataStore
    CatalogMicroservice3 --> MySQLDataStore

    TicketingMicroservice1 --> MySQLDataStore
    TicketingMicroservice2 --> MySQLDataStore
    TicketingMicroservice3 --> MySQLDataStore

    SearchMicroservice1 --> ApacheSolr
    SearchMicroservice2 --> ApacheSolr
    SearchMicroservice3 --> ApacheSolr

轉型過程中的架構變化

在轉型為微服務之前,產品目錄、票務和搜尋等功能都是單一的巨石應用程式的一部分。這些功能在轉型後被拆分成獨立的微服務,每個微服務都有自己的建置和佈署流程。這些微服務在負載平衡器後執行,以確保高用性和擴充套件性。

轉型步驟及細節

以下是將產品目錄功能轉型為獨立微服務的詳細步驟:

1. 建立新專案

首先,建立一個新的 Eclipse 專案,命名為 catalog-svc。這將是新的產品目錄微服務專案。

2. 安裝 Apache Maven

下載並安裝 Apache Maven,這是一個現代且靈活的建置系統,具有優越的外部依賴管理功能。可以參考 Apache Maven 安裝

3. 建立 Maven pom.xml 檔案

在專案的根目錄中建立一個 pom.xml 檔案,定義專案所需的依賴項。可以參考 GitHub 上的範例: catalog-svc pom.xml

4. 建立必要的類別和組態檔案

根據微服務定義,建立以下類別和組態檔案:

  • Service Interface:定義產品目錄的操作介面。
  • Service Implementation:實作上述介面的具體邏輯。
  • Service Helper:輔助類別,提供一些輔助方法。
  • DAO (Data Access Object):資料存取物件類別,處理資料函式庫操作。
  • Application Context XML:定義 Spring 框架中的 Bean 組態。

以下是部分最佳化後的範例碼:

public interface CatalogService extends BeanFactoryAware, ApplicationContextAware {
    ProductDetailsResponse getCatalog(@Context HttpHeaders headers, String userId) throws ServiceInvocationException;
    CatalogResponse addCatalog(@Context HttpHeaders headers, CatalogRequest req) throws ServiceInvocationException;
    CatalogResponse updateCatalog(@Context HttpHeaders headers, CatalogRequest req) throws ServiceInvocationException;
    CatalogResponse deleteCatalog(@Context HttpHeaders headers, CatalogRequest req) throws ServiceInvocationException;
}
@Component
@Path("/CatalogService")
public class CatalogServiceImpl implements CatalogService {
    @Override
    @GET
    @Consumes({"application/xml", "application/json"})
    @Produces({"application/json"})
    @Path("/getCatalog/{customerId}")
    public ProductDetailsResponse getCatalog(@Context HttpHeaders headers, @PathParam("customerId") String customerId) throws ServiceInvocationException {
        // 實作取得產品詳細資料的邏輯
        return new ProductDetailsResponse();
    }
}
public class CatalogServiceHelper {
     private CatalogDao dao = null;
     // 輔助方法實作...
}
public class CatalogDao extends DataService {
     // 資料存取邏輯實作...
}

5. 組態 applicationContext.xml

修改 applicationContext.xml 檔案,只定義這個微服務所需的 Bean。新的專案結構如下圖所示:

此圖示表示新的專案結構,包括各種必要的類別和組態檔案。
graph TD;
A["src"] -- "main" -- B["java"];
A["src"] -- "main" -- C["resources"];
B -- D["com.example.catalog"];
D -- E["service"];
D -- F["dao"];
D -- G["helper"];
C -- H["applicationContext.xml"];

6. 建置並佈署 WAR 檔案

使用 Maven 命令 mvn install 建置 WAR 檔案。然後將這個 WAR 檔案佈署到 Tomcat 伺服器上。佈署後,Web 伺服器端點會改變為:

http://<host>:<port>/catalog-svc/rest/catalogservice/<Rest Verb>

7. 組態資料函式庫連線

在建置 WAR 檔案之前,修改 applicationContext.xml 中的資料函式庫組態,確保連線到正確的資料函式庫。

<bean id="DataSource" destroy-method="close" class="org.apache.tomcat.jdbc.pool.DataSource">
     <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
     <property name="url" value="jdbc:mysql://<dbhost>:<dbport>/<dbname>"/>
     <!-- 其他資料函式庫組態 -->
</bean>

轉型過程中的注意事項

在轉型過程中,需要特別注意以下幾點:

  • 依賴管理:確保只包含新微服務所需的第三方依賴。
  • 建置系統:使用 Apache Maven 作為建置系統,因為它具有更好的外部依賴管理功能。
  • 升級依賴:升級第三方依賴到最新版本,以利用最新的改進和安全修補。

轉型完成後的測試與驗證

在轉型完成後,必須進行全面測試以確保新的微服務正常執行。測試內容包括功能測試、效能測試以及整合測試等。

及技術挑戰

未來可能會面臨更多技術挑戰,例如何進行有效的跨微服務溝通、如何實作高用性和故障還原、以及如何進行持續整合和持續佈署(CI/CD)等。這些問題需要透過不斷學習和實踐來解決。

玄貓強調轉型為微服務是一個循序漸進的過程,需要不斷地最佳化和改進。每個階段都應該進行詳細的分析和評估,以確保系統穩定性和可靠性。

轉換為微服務架構

在現代軟體開發中,微服務架構(Microservices Architecture)已成為一種主流的設計模式。它將大型單體應用程式拆分為多個獨立的小型服務,這些服務可以獨立佈署和擴充套件。以下是將傳統單體應用程式轉換為微服務架構的具體實踐與考量。

產品目錄微服務

將產品目錄模組從單體應用程式中拆分出來,並建立獨立的建置實體,這包括介面、服務實作、輔助類別及組態檔案。以下是一個簡單的資料函式庫連線組態範例:

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/yourDatabase"/>
    <property name="username" value="yourUsername"/>
    <property name="password" value="yourPassword"/>
    <property name="initialSize" value="5"/>
    <property name="maxActive" value="50"/>
    <property name="validationQuery" value="SELECT 1"/>
    <property name="testWhileIdle" value="true"/>
    <property name="testOnBorrow" value="true"/>
    <property name="minIdle" value="5"/>
    <property name="minEvictableIdleTimeMillis" value="3000000"/>
    <property name="timeBetweenEvictionRunsMillis" value="600000"/>
    <property name="removeAbandoned" value="true"/>
    <property name="removeAbandonedTimeout" value="30000"/>
    <property name="logAbandoned" value="true"/>
    <property name="maxWait" value="120000"/>
</bean>

內容解密:

上述範例展示瞭如何使用Apache Commons DBCP(Database Connection Pooling)來組態資料函式庫連線。以下是每個屬性的詳細說明:

  • driverClassName:指定資料函式庫驅動程式。
  • url:資料函式庫連線URL。
  • username:資料函式庫使用者名稱。
  • password:資料函式庫密碼。
  • initialSize:初始化時建立的連線數。
  • maxActive:連線池中的最大活躍連線數。
  • validationQuery:用於檢查連線有效性的SQL陳述式。
  • testWhileIdle:是否在閒置時檢查連線有效性。
  • testOnBorrow:是否在從連線池中取得連線時檢查有效性。
  • minIdle:連線池中的最小閒置連線數。
  • minEvictableIdleTimeMillis:連線在閒置多久後可以被釋放。
  • timeBetweenEvictionRunsMillis:執行驅逐任務的時間間隔。
  • removeAbandoned:是否移除遺棄的連線。
  • removeAbandonedTimeout:遺棄連線在多久後被移除。
  • logAbandoned:是否記錄遺棄的連線。
  • maxWait:從連線池中取得連線時的最大等待時間。

工單微服務

工單管理也是從單體應用程式中拆分出來的一個模組。這些步驟與產品目錄的轉換相似,包括介面、服務實作、輔助類別及組態檔案。由於這部分的技術細節與產品目錄類別似,此處不再重複說明。

搜尋微服務

搜尋功能通常需要更高效的索引和查詢能力。因此,我們選擇使用Apache Solr來增強搜尋功能。以下是如何將搜尋功能轉換為微服務的詳細步驟。

資料函式庫基礎搜尋

首先,我們將原本根據資料函式庫的搜尋功能拆分出來,形成獨立的建置實體。這包括介面、服務實作、輔助類別及組態檔案。

Solr基礎搜尋

首先,安裝並組態Solr引擎。安裝完成後,我們可以建立Solr-based search微服務。以下是使用Solr進行查詢的一個簡單範例:

@POST
@Consumes({"application/xml", "application/json"})
@Produces({"application/json"})
@Path("/solrSearch")
public QueryResponse search(@Context HttpHeaders headers, SearchRequest request) {
    HttpSolrServer solr = new HttpSolrServer("http://<solr_host_ip>:8983/solr/helpdesk");
    SolrQuery query = new SolrQuery();
    query.setQuery(request.getQuery());
    query.setStart(0);
    return solr.query(query);
}

內容解密:

上述範例展示瞭如何使用Solr進行查詢操作。以下是每個部分的詳細說明:

  • @POST:指定該方法處理POST請求。
  • @Consumes:指定該方法可以接受的媒體型別(XML或JSON)。
  • @Produces:指定該方法傳回的媒體型別(JSON)。
  • @Path("/solrSearch"):指定該方法的URL路徑。
  • HttpSolrServer solr = new HttpSolrServer("http://<solr_host_ip>:8983/solr/helpdesk"):建立一個Solr伺服器物件,並指定Solr伺服器的URL。
  • SolrQuery query = new SolrQuery():建立一個Solr查詢物件。
  • query.setQuery(request.getQuery()):設定查詢條件。
  • query.setStart(0):設定查詢起始位置。
  • return solr.query(query):執行查詢並傳回結果。

應用程式建置與佈署

在轉換為微服務架構後,我們需要重新思考建置和佈署流程。以下是一些具體步驟和考量。

程式碼設定

原本使用Apache Ant進行建置的單體應用程式,現在轉為使用Apache Maven進行建置。Maven提供了更強大的依賴管理功能,適合微服務架構中的模組化需求。

mvn clean package

此命令會清理舊有建置產物並生成新的WAR檔案,準備佈署到應用程式伺服器(如Tomcat)。

佈署與組態

佈署微服務有多種選擇,每種選擇都有其優缺點。以下是一些常見的佈署策略:

  1. 單機多服務:在同一台機器上佈署多個微服務,優點是資源利用率高,但缺點是依賴單一機器可能影響可靠性。
  2. 分散式佈署:將每個微服務佈署到不同的機器上,優點是提高可靠性和擴充套件性,但缺點是管理複雜度增加。

視覺化圖表

此圖示展示了從單體應用程式轉換為微服務架構的過程:

@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

內容解密:

上述Plantuml圖表展示了從單體應用程式拆分出三個獨立微服務的過程:

  1. A表示原始單體應用程式。
  2. B表示產品目錄微服務。
  3. C表示工單管理微服務。
  4. D表示搜尋微服務。

透過這些步驟和考量,我們成功地將傳統單體應用程式轉換為現代化、模組化且具有高可擴充套件性和靈活性的微服務架構。