服務編排

一. 背景 

  1. 應用系統的架構演變隨著業務的越來越複雜,需要更多的思考、更高維度的抽象。
  2. 將組織邏輯與業務實現分離,使業務應用更關注自身的領域內容。

二. 目標

  將業務流程可視化、最終展現出全局業務視圖,並可以動態調整業務鏈路。結尾附上示例程式碼。

  大部分現行的系統都是通過繁榮的程式碼來實現業務邏輯的拼裝,當業務變得極其複雜的時候會變得可讀性極差,可維護性降低。

  服務編排的理想目標是開發人員只注重簡單介面(行為)的開發,業務人員可以通過編排系統實現應用及系統的組裝和運維。簡單一點理解的話就是講服務化衍進為工具化(理想狀態,現實很難)。

三. 產出 

  1. 一個中心化的流程配置站點,效果如圖(引用zeebe的系統圖)
  2. 一個輕量級的編排網關,使用網關模式(中心化)、業務介面將不直接暴露服務,所有請求由網關組織,類似匯流排模式。優點在於對於新的應用,開發者只需關注自己的原子功能實現,缺點在於對於舊的應用,部分業務介面需要拆解改造。
  3. 一個客戶端代理,使用代理模式(非中心化)、中心化的配置站點根據版本下發規則文件,需要在各自應用系統中引用代理組件,可以自動/按需進行服務組織調用與上下文適配。

    ps:對於網關模式和代理模式一般只需要採取1種,具體根據自己的實際場景選擇。

四. 與工作流區別

  1. 從實現方向上來說,工作流引擎的核心實現是一種狀態機、可以理解成一套中心化的服務;服務編排的核心是一套開發框架,它依賴接入應用的具體場景。
  2. 從業務方向來說,工作流引擎側重構建定義執行過程,強調規範、快速開發;服務編排側重業務建模、組裝、部署及管理。
  3. 從使用場景來說,工作流引擎一室現在最大的使用場景為辦公自動化;服務編排可以理解成SOA的產物。

五. 應用場景分析

  

  簡單的來說,這種場景對應網關模式,無需程式碼侵入,由編排網關統籌管理服務調度,粒度可以足夠的細,一次db操作,一次文件操作,一次介面調用都可以作為調度的基本單元。端點的概念在後面實現里會講。

這種場景為代理模式,需要少量的程式碼侵入,侵入部分為編排的組件代理,這種模式可以解決中心化的問題,各自應用自己治理。

  宏觀的概念為企業應用模式,通過編排引擎將應用系統、數據資源和互聯網資源組成一個統一的整體。看起來是不是和ESB有點像,很快我們會總結和ESB的差異。

  核心模組參考Netflix conductor 、Zeebe、Apache Camel等成熟產品 結合我們自己業務特性,目標為輕量級、可擴展、組件化的設計模式。

   黃色的部分就是服務編排組件和ESB產品重疊的內容,服務編排組件相當於是ESB產品成熟架構之上的一些功能拆解,並逐漸衍生為更貼合互聯網主流技術(例如微服務)的替代方案。

  上面我們聊了2種模式,我們通過管道與業務域的關係來解釋部署方案的差異

  管道是消息傳遞的載體。由於編排引擎的核心為組件化的實現方式,其部署的方式相對靈活。

  1. 管道的範圍決定了業務域的大小 高緯度能以整個團隊業務為維度,低緯度能以個別應用為維度。

  2. 中心化部署 好處是可以避免下層應用程式碼的侵入並集中管理

  3.非中心化部署 非中心化部署有2種方式

    i)第一種為程式碼植入,這種方式不依賴管道作為消息載體,每一個植入應用都屬於消息載體,並直接管理上下文。

    ii)第二種為ServiceMesh的邊車模式,將控制與業務分離。好處是無需進行程式碼侵入,缺點是當前環境該模式並不成熟,容易帶入運維成本。

  除了路由可視化,還可以利用JMX實現擴展管理,Mbean中包含了所有可更新對象。 消息管道中按每筆事件定義通訊ID,通訊ID在一次傳遞過程中不會變化,其中包含版本資訊。 新版本的產生不會影響到舊的事件。

六. 核心組件實現

重點參考開源產品Apache Camel。最核心的是DSL語言、端點、組件、路由、註冊表、格式轉化。

DSL 其實是 Domain Specific Language 的縮寫,相對DSL的定義就是 GPL(General Purpose Language)

常見的DSL有SQL、Regex ,常見的GPL有Objective-C、Python…

DSL 最大的設計原則就是簡單,通過簡化語言中的元素,降低使用者的負擔設計語法和語義。Camel組件中設計DSL語法和語義,定義 DSL 中的元素並實現 parser,對 DSL 解析,最終通過解釋器來執行。目前支援Java DSL和XML DSL。其核心定義就是描述了一次路由行為的上下文、內容、類型、依賴、邏輯等等。運行時編排系統就會載入實現定義的DSL文件,會按照DSL文件中定義的路由行為來執行。

回到上面提出的問題,什麼是端點(Endpoint)。端點是camel的抽象概念。可以理解成信道末端模型,系統可以利用信道收發消息。更通俗一點來講,你可以將端點理解成一次通訊行為的支撐/目標支點。這個支點可以支援非常多的協議,例如http、ftp、rpc等等等等。這從基礎上就決定了我們的通訊信道不僅僅可以支撐現在常用的服務/微服務場景,更能從更多底層元素來運作編排行為。

但是端點需要滿足一定的規則要求,首先是路由Url,示例中的file代表Scheme,定義了端點的協議類型。Context path定義通訊的路徑及埠等。Options定外額外的一些擴展資訊,根據協議和場景的特殊性可以自定義邏輯和內容。

端點還關聯著生產者、消費者、交換機等概念,這些內容的設計和實現和RabbitMq同源,RabbitMq的底層設計就是使用了Camel的框架。

關於這些概念可以參與我之前的文章 //www.cnblogs.com/dubing/p/4017613.html

組件的概念如下圖

組件的實現方式為監控指定目錄中的文件。此目錄中的文件描述了組件的名稱、組件類的全路徑名。 大部分組件的java程式碼模組都與模組核心模組做了分離,因為他們常常依賴第三方的包,如果不分離,將會使核心包過度膨脹。

整個端點實現的類圖可以參考下圖

下面我們接著講路由

 

Multicast表示將消息複製多份串列/並行分開給所有消費通道。

RecipientList區別於多播模式,解決消費通道優先順序問題。收件人列表可以動態維護。

routeSliping是將消息依次傳入後面的節點進行處理,不會負責,後面的節點修改的是同一個消息。

此外還有多種傳遞類型,例如SPLIT將一份消息分離成不同部分傳遞給不同消息通道,Aggregator將不同消息來源合併給下游消息通道。

如果組件支援的模式不足以滿足我們項目的特性需求還可以自定義規則

示例中根據choice-when 自定義路由規則。

程式碼示例

本章總覽了服務編排的設計,內容較多每一塊的細節都可以單獨拿出來詳細解讀,最後附上組件示例程式碼(示例程式碼為完全demo環境,如發現任何企業或者版權相關資訊請聯繫我刪除)

組件示例下載