隨著業務發展和系統規模擴大,傳統單體應用逐漸顯露出其瓶頸,例如擴充套件性差、佈署效率低、技術堆疊受限等。為瞭解決這些問題,許多企業開始將目光轉向微服務架構。本文以一個幫助台應用為例,詳細介紹瞭如何將其從單體架構逐步遷移至微服務架構。過程中,我們將商品目錄、工單和搜尋等核心服務拆分為獨立的微服務,並採用 Maven 管理專案依賴和建置流程。針對資料函式庫搜尋的效能瓶頸,我們引入了 Solr 搜尋引擎,並透過 RESTful API 與之整合。此外,我們還探討了不同的微服務佈署策略,包括多服務分享伺服器、虛擬機器獨立佈署和容器化佈署,分析了各自的優缺點,並提供程式碼範例和組態說明,幫助讀者更好地理解和實踐微服務架構。最後,我們也簡要討論了未來技術趨勢和選型考量,例如容器化技術 Docker 的應用和挑戰,鼓勵讀者持續學習和探索。

從單體應用轉換為微服務架構

在現代軟體開發中,從單體應用轉換為微服務架構已成為一個重要的趨勢。這種轉變不僅能提高系統的靈活性和可擴充套件性,還能促進開發團隊的協作效率。以下是玄貓(BlackCat)在這個過程中的具體操作與實務經驗分享。

商品目錄服務轉換

商品目錄服務是幫助台桌應用的一部分,將其從單體應用中分離出來,形成獨立的建置實體。這包括將介面、服務實作、輔助類別和組態檔案移出,並建立新的建置藝術品。新的建置藝術品僅包含新建置實體所需的第三方依賴。

<property name="username" value="<Username>"/>
<property name="password" value="<Password>"/>
<property name="initialSize" value="5"/>
<property name="maxActive" value="50"/>
<property name="validationQuery" value="select 1 from dual"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="true"/>
<property name="minIdle" value="20000"/>
<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"/>

內容解密:

上述程式碼為資料函式庫連線池的組態設定,這些設定專案包括使用者名稱、密碼、初始化連線數量、最大連線數量、驗證查詢陳述式等,主要用於管理資料函式庫連線的生命週期和連線池的行為。

商品目錄服務會改用Apache Maven來進行建置,因為Maven能夠更好地管理依賴關係和模組化建置。這樣做可以讓開發流程更加穩定且易於維護。

工單服務轉換

工單服務與商品目錄服務類別似,將其從單體應用中分離出來,形成獨立的建置實體。這也是一個將介面、服務實作、輔助類別和組態檔案移出,並建立新建置藝術品的過程。新的建置藝術品僅包含新建置實體所需的第三方依賴。

工單服務也會改用Apache Maven來進行建置。步驟與商品目錄服務相同,首先將相關程式碼和組態檔案分離出來,然後使用Maven進行建置和依賴管理。

搜尋服務轉換

目前我們有一個根據資料函式庫的基本搜尋服務。為了提供更先進的搜尋功能,我們引入了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://<ip of solr host>:8983/solr/helpdesk");
    SolrQuery query = new SolrQuery();
    query.setQuery(request.getQuery());
    query.setStart(0);
    return solr.query(query);
}

內容解密:

上述程式碼是一個根據Spring Framework的RESTful API端點,用於處理Solr搜尋請求。當收到HTTP POST請求時,會根據請求內容建構Solr查詢陳述式並傳送到指定的Solr伺服器,最後傳回查詢結果。

為了安裝和組態Solr引擎,請參考附錄B中的詳細說明。一旦Solr伺服器啟動並執行正常,我們就可以開始構建微服務。我們會將先進搜尋服務建立為獨立實體,並利用Apache Maven來建置藝術品。

應用程式建置與佈署

我們已經將幫助台桌應用中的三個元件轉換為獨立的微服務:

  1. 商品目錄
  2. 工單
  3. 搜尋

建置流程

原本的單體應用使用Apache Ant進行建置,但隨著專案越來越模組化且需要管理依賴關係,我們改用Apache Maven來進行建置。Ant雖然可以使用Ivy來補充依賴管理功能,但Maven在這方面具有天生優勢。

這些微服務的原始碼可以在GitHub上找到:https://github.com/kocherMSD/Helpdesk_Microservices.git

命令列建置

要透過命令列來建置Maven專案,可以在包含相關POM檔案的專案目錄中執行mvn clean package命令。這個命令會清除舊有藝術品並將其封裝成WAR檔案,準備好佈署。

透過Eclipse自動化建置

在Eclipse中匯入專案後,右鍵點選專案名稱,選擇「Run As」,然後選擇「Run Configurations」。在Run Configurations視窗中,輸入clean package到Goals欄位並點選「Run」。這樣就可以清理舊有藝術品並生成WAR檔案,準備好佈署到Tomcat等應用容器中。

佈署與組態選項

佈署微服務有多種選項,每種選項都有其優缺點。以下是幾種常見的佈署方式:

  1. 多個微服務在同一台機器上:這種方式將多個微服務佈署在同一台物理或虛擬機器上。優點是資源利用率高,但缺點是如果某個微服務出現問題可能會影響其他微服務。

  2. 每個微服務獨立佈署:這種方式將每個微服務佈署在不同的機器上。優點是隔離性好,但缺點是資源利用率可能不高。

  3. 容器化佈署:使用Docker等容器技術來佈署微服務。優點是可移植性強且資源利用率高。

  4. Kubernetes協調:使用Kubernetes來管理和協調多個微服務。優點是可擴充套件性強且自動化程度高。

這些佈署方式都有各自的適用場景和優缺點,具體選擇需要根據具體需求來決定。

微服務遷移實戰:將傳統應用轉型為現代化架構

在現代軟體開發中,微服務架構已成為一種主流的設計模式。它透過將大型單一應用拆分為多個小型、獨立的服務,來提升系統的靈活性和可擴充套件性。玄貓在此將探討如何將一個傳統的幫助台應用從單一體系結構遷移到微服務架構,並提供具體的實作步驟和技術選型分析。

微服務佈署策略

在實施微服務架構時,佈署策略是關鍵之一。以下是幾種常見的佈署策略及其優缺點:

多個微服務分享同一伺服器

這種策略下,多個微服務或例項分享同一伺服器的資源(CPU、記憶體、I/O等)。其優點是資源利用率較高,但缺點是缺乏隔離性,一個異常的微服務可能會影響到其他服務。

每個微服務獨立佈署在虛擬機器

每個微服務執行在獨立的虛擬機器中,這樣可以確保每個微服務完全隔離。每個微服務有完整的資源組態(記憶體、CPU、I/O),但這種方式資源利用率較低,且虛擬機器的啟動速度較慢。

每個微服務獨立佈署在容器中

容器化技術如Docker使得這種方式變得可行。每個微服務執行在獨立的容器中,容器提供了輕量級的隔離環境,資源消耗可以被監控和管理。此外,容器啟動速度快,適合動態擴充套件和自動化佈署。

實施步驟:將幫助台應用遷移至微服務

玄貓將以具體案例來說明如何將幫助台應用從單一體系結構遷移到微服務架構。以下是詳細步驟:

1. 組態新增微服務的連線端點

首先,我們需要修改現有單一體系結構應用中的屬性檔案Application.properties,將新增的微伺服器端點進行組態:

endPoints.searchEndPoint=http://host:port/search-svc/rest/SearchService/search
endPoints.getCatalog=http://host:port/ticketing-svc/rest/CatalogService/getCatalog
endPoints.createTicket=http://host:port/catalog-svc/rest/TicketService/createTicket

2. 修改搜尋檢視以呼叫新的搜尋端點

接著,我們需要修改單一體系結構應用中的search.jsp檔案,新增進階搜尋按鈕並呼叫Solr搜尋API:

function solrsearch() {
    var solrSearchEndPoint = "<%= props.getProperty('endPoints.solrSearchEndPoint') %>";
    var searchText = document.getElementById("searchText").value;
    if (searchText == '') {
        alert('請輸入搜尋文字');
        return;
    }
    var dataToSend = { "query": searchText };
    $.ajax({
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        url: solrSearchEndPoint,
        type: 'POST',
        dataType: 'json',
        data: JSON.stringify(dataToSend),
        success: function (data, textStatus, jqXHR) {
            $("#solrresults").empty();
            var docs = data.results;
            $.each(docs, function (i, item) {
                $('#solrresults').prepend($('<div>' + objToString(item) + '</div>'));
            });
            var total = '找到 ' + docs.length + ' 個結果';
            $('#solrresults').prepend('<div>' + total + '</div>');
        }
    }).fail(function (jqXHR, textStatus, error) {
        alert(jqXHR.responseText);
    });
}

3. 建立並佈署獨立的微服務WAR檔案

使用Apache Maven建置每個獨立的微服務WAR檔案。以下是範例建置指令:

mvn clean install

建置成功後,會看到類別似以下的輸出:

[INFO] Building war: /opt/projects/BOOKCODE/catalog-svc/target/catalog-svc.war
[INFO] 
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
[INFO] BUILD SUCCESS
[INFO] 
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-

4. 建立並組態Tomcat目錄結構

將所有建置好的WAR檔案複製到Tomcat的webapps目錄中。最終目錄結構應如下所示:

search-svc
catalog-svc
docs
helpdesk
host-manager
ROOT
ticketing-svc.war
search-svc.war
catalog-svc.war
examples
helpdesk.war
manager
ticketing-svc

新需求與錯誤修正

在轉型過程中,我們也遇到了一些新需求與錯誤修正。例如,當我們需要在「檢視票券」服務中新增額外引數時,可以透過以下程式碼來進行修改:

public TicketResponse createHdTicket(
    @Context HttpHeaders headers,
    TicketRequest ticketRequest)
    throws ServiceInvocationException {
    // 新增引數處理邏輯
}

未來趨勢與技術選型考量

在遷移過程中,我們也需要考慮未來技術趨勢及選型。例如,容器化技術如Docker已經成為主流,但在安全性和大規模管理方面仍有挑戰。因此,我們需要持續監控技術發展並進行適時調整。

總結來說,從單一體系結構轉型為微服務架構是一個複雜但必要的過程。透過合理的技術選型和詳細的實作步驟,我們可以成功完成這次轉型並為未來的發展打下堅實基礎。

此圖示展示了多種佈署方式之間關係與技術選型考量

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 單體應用轉換微服務架構實踐與佈署策略

package "Docker 架構" {
    actor "開發者" as dev

    package "Docker Engine" {
        component [Docker Daemon] as daemon
        component [Docker CLI] as cli
        component [REST API] as api
    }

    package "容器運行時" {
        component [containerd] as containerd
        component [runc] as runc
    }

    package "儲存" {
        database [Images] as images
        database [Volumes] as volumes
        database [Networks] as networks
    }

    cloud "Registry" as registry
}

dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置

@enduml
圖解:
  • A:傳統單一體系結構應用。
  • B:多個微服務分享同一伺服器。
  • C:每個微服務獨立佈署在虛擬機器。
  • D:每個微服務獨立佈署在容器中。
  • E:高效利用伺服器資源。
  • F:缺乏隔離性。
  • G:提供完全隔離環境。
  • H:資源利用率低。
  • I:輕量級隔離環境。
  • J:快速啟動和佈署。

內容解密:

  • 上述程式碼展示瞭如何修改屬性檔案以組態新增的微伺服器端點。
  • JavaScript 函式實作了與 Solr 搜尋 API 的互動並更新搜尋結果檢視。
  • Maven 命令 用於構建單個獨立的 WAR 包檔案。
  • Docker 容器 在現代化應用開發中佔據重要地位。
  • Plantuml圖表 用於清晰地描繪不同佈署方式之間的關係及其優缺點。

自行動手操作並深入學習

玄貓希望透過這些實際操作和深度分析,讓大家更瞭解如何從傳統應用轉型為現代化架構。記得保持持續學習和實踐精神,確保自己不斷進步和成長!