一. 背景
- 應用系統的架構演變隨著業務的越來越複雜,需要更多的思考、更高維度的抽象。
- 將組織邏輯與業務實現分離,使業務應用更關注自身的領域內容。
二. 目標
將業務流程視覺化、最終展現出全域性業務檢視,並可以動態調整業務鏈路。理解這句話很重要,下文所有的開展都是圍繞這個目標。結尾附上元件示例程式碼。
大部分現行的系統都是通過繁榮的程式碼來實現業務邏輯的拼裝,當業務變得極其複雜的時候會變得可讀性極差,可維護性降低。
服務編排的理想目標是開發人員只注重簡單介面(行為)的開發,業務人員可以通過編排系統實現應用及系統的組裝和運維。簡單一點理解的話就是講服務化衍進為工具化(理想狀態,現實很難)。
三. 產出
- 一箇中心化的流程配置站點,效果如圖(引用zeebe的系統圖)
- 一個輕量級的編排閘道器,使用閘道器模式(中心化)、業務介面將不直接暴露服務,所有請求由閘道器組織,類似匯流排模式。優點在於對於新的應用,開發者只需關注自己的原子功能實現,缺點在於對於舊的應用,部分業務介面需要拆解改造。
- 一個客戶端代理,使用代理模式(非中心化)、中心化的配置站點根據版本下發規則檔案,需要在各自應用系統中引用代理元件,可以自動/按需進行服務組織呼叫與上下文適配。
ps:對於閘道器模式和代理模式一般只需要採取1種,具體根據自己的實際場景選擇。
四. 與工作流區別
- 從實現方向上來說,工作流引擎的核心實現是一種狀態機、可以理解成一套中心化的服務;服務編排的核心是一套開發框架,它依賴接入應用的具體場景。
- 從業務方向來說,工作流引擎側重構建定義執行過程,強調規範、快速開發;服務編排側重業務建模、組裝、部署及管理。
- 從使用場景來說,工作流引擎一室現在最大的使用場景為辦公自動化;服務編排可以理解成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的框架。
關於這些概念可以參與我之前的文章 https://www.cnblogs.com/dubing/p/4017613.html
元件的概念如下圖
元件的實現方式為監控指定目錄中的檔案。此目錄中的檔案描述了元件的名稱、元件類的全路徑名。 大部分元件的java程式碼模組都與模組核心模組做了分離,因為他們常常依賴第三方的包,如果不分離,將會使核心包過度膨脹。
整個端點實現的類圖可以參考下圖
下面我們接著講路由
Multicast表示將訊息複製多份序列/並行分開給所有消費通道。
RecipientList區別於多播模式,解決消費通道優先順序問題。收件人列表可以動態維護。
routeSliping是將訊息依次傳入後面的節點進行處理,不會負責,後面的節點修改的是同一個訊息。
此外還有多種傳遞型別,例如SPLIT將一份訊息分離成不同部分傳遞給不同訊息通道,Aggregator將不同訊息來源合併給下游訊息通道。
如果元件支援的模式不足以滿足我們專案的特性需求還可以自定義規則
示例中根據choice-when 自定義路由規則。
程式碼示例
本章總覽了服務編排的設計,內容較多每一塊的細節都可以單獨拿出來詳細解讀,最後附上元件示例程式碼(示例程式碼為完全demo環境,如發現任何企業或者版權相關資訊請聯絡我刪除)