一文讀懂微服務(wù)編排利器—Zeebe

一、工作流與微服務(wù)編排
1. 工作流
(1)沒有工作流時的任務(wù)協(xié)作


(2)應(yīng)用工作流模型的任務(wù)協(xié)作


2. 工作流引擎

3. 微服務(wù)編排
可見性:多少端到端業(yè)務(wù)流正在運行中,它們的狀態(tài)是什么樣子。過去24小時,有多少業(yè)務(wù)流實例沒有成功結(jié)束?為什么這些業(yè)務(wù)流實例沒有成功結(jié)束?一個業(yè)務(wù)流或者某個任務(wù)完成的平均時間是多少?
異常處理:如果業(yè)務(wù)流里有一個微服務(wù)失敗,誰負責(zé)處理這個異常?業(yè)務(wù)流的重試邏輯是怎么樣的?如果需要人工介入,問題的升級處理規(guī)則是怎么樣的?
按照業(yè)務(wù)邏輯的藍圖,編排各個微服務(wù)的調(diào)用關(guān)系;
監(jiān)控整個業(yè)務(wù)流的狀態(tài);
提供自動化的機制處理單個服務(wù)的失敗,保證整個業(yè)務(wù)流的成功。

傳統(tǒng)的工作流引擎,編排的大部分是人工審批任務(wù),意味著任務(wù)流轉(zhuǎn)效率低,系統(tǒng)吞吐低。而當(dāng)下微服務(wù)大部分是程序化的自動任務(wù),意味著任務(wù)高效流轉(zhuǎn),系統(tǒng)吞吐高。單點架構(gòu)、同步響應(yīng)、高度依賴DB的Activiti,顯然支撐不了這樣的場景。

Activiti等工作流引擎,通常都以jar包的形式,嵌入到業(yè)務(wù)程序中,直接通過調(diào)用本地方法的方式調(diào)度起業(yè)務(wù)TaskHandler。在單體架構(gòu)下,這種集成方式簡單易用。但是在微服務(wù)架構(gòu)下,工作流的任務(wù)往往是分布在多個服務(wù)的,而且同一個服務(wù)往往還會根據(jù)負載情況部署不同數(shù)量的實例。如果還是采用引擎主動調(diào)用的方式,怎么尋址到具體的TaskHandler?當(dāng)后端業(yè)務(wù)服務(wù)處理能力本身是瓶頸的時候,如果引擎還是不斷的調(diào)用,只會進一步壓垮服務(wù)。

二、Zeebe特性與頂層架構(gòu)
1. Zeebe核心特性
可見性(visibility):Zeebe提供能力展示出企業(yè)工作流運行狀態(tài),包括當(dāng)前運行中的工作流數(shù)量、平均耗時、工作流當(dāng)前的故障和錯誤等;
工作流編排(workflow orchestration):基于工作流的當(dāng)前狀態(tài),Zeebe以事件的形式發(fā)布指令(command),這些指令可以被一個或多個微服務(wù)消費,確保工作流任務(wù)可以按預(yù)先的定義流轉(zhuǎn);
監(jiān)控超時(monitoring for timeouts)或其他流程錯誤:同時提供能力配置錯誤處理方式,比如有狀態(tài)的重試或者升級給運維團隊手動處理,確保工作流總是能按計劃完成。
橫向擴容(horizontal scalability):Zeebe支持橫向擴容并且不依賴外部的數(shù)據(jù)庫,相反的,Zeebe直接把數(shù)據(jù)寫到所部署節(jié)點的文件系統(tǒng)里,然后在集群內(nèi)分布式的計算處理,實現(xiàn)高吞吐;
容錯(fault tolerance):通過簡單配置化的副本機制,確保Zeebe能從軟硬件故障中快速恢復(fù),并且不會有數(shù)據(jù)丟失;
消息驅(qū)動架構(gòu)(message-driven architecture):所有工作流相關(guān)事件被寫到只追加寫的日志(append-only log)里;
發(fā)布-訂閱交互模式(publish-subscribe interaction model):可以保證連接到Zeebe的微服務(wù)根據(jù)實際的處理能力,自主的消費事件執(zhí)行任務(wù),同時提供平滑流量和背壓的機制;
BPMN2.0標(biāo)準(zhǔn)(Visual workflows modeled in ISO-standard BPMN 2.0):保證開發(fā)和業(yè)務(wù)能夠使用相同的語言協(xié)作設(shè)計工作流;
語言無關(guān)的客戶端模型(language-agnostic client model):可以使用任何編程語言構(gòu)建Zeebe客戶端。
2. Zeebe架構(gòu)

(1)Client
發(fā)布工作流(deploy workflows)
執(zhí)行業(yè)務(wù)邏輯(carry out business logic)
處理運維問題(handle operational issues)
處理客戶端發(fā)送的指令 存儲和管理運行中流程實例的狀態(tài) 分配任務(wù)給job workers
監(jiān)控當(dāng)前運行流程實例的狀態(tài) 分析歷史的工作流數(shù)據(jù)以做審計或BI 跟蹤Zeebe拋出的異常(incident)
三、Zeebe內(nèi)部核心實現(xiàn)

Zeebe Broker內(nèi)部使用隊列(即LogStream,只追加寫),異步處理請求; Zeebe JobWorker和Broker使用發(fā)布訂閱的模式交互,當(dāng)工作流任務(wù)狀態(tài)發(fā)生變化,Broker會發(fā)布相應(yīng)事件。JobWorker通過輪詢的方式,訂閱處理自己相關(guān)的事件。
指令協(xié)議(command protocol,即請求響應(yīng)) 記錄導(dǎo)出(record export / streaming) 工作流演算(evaluation, 異步后臺任務(wù))


客戶端發(fā)送指令。例如:發(fā)布工作流、啟動流程實例、創(chuàng)建和完成任務(wù)等; broker自身產(chǎn)生指令。例如:查找可以被worker執(zhí)行的任務(wù)。
從流里消費指令(command) 根據(jù)狀態(tài)生命周期和實體當(dāng)前狀態(tài),判斷指令是否適用 如果指令適用,應(yīng)用到狀態(tài)機。如果指令是客戶端發(fā)送的,發(fā)送回響應(yīng)。 如果指令不適用,拒絕。如果是客戶端發(fā)過來的,發(fā)送錯誤響應(yīng)信息。 發(fā)布新的事件,報告實體新的狀態(tài)。
4jpublic class SomeJob {(type = "some-service.SomeJob")public void handleTask(final EnhancedJobClient client, final ActivatedJob job) {// 業(yè)務(wù)邏輯// ....// 根據(jù)業(yè)務(wù)邏輯執(zhí)行情況,結(jié)單if (success) {client.completeJob(job);} else {throw SomeException("失敗原因");}}



通過把歷史數(shù)據(jù)推到外部數(shù)據(jù)倉庫中,持久化歷史數(shù)據(jù) 把記錄導(dǎo)出到可視化工具中(例如: zeebe-simple-monitor)
exporter id不唯一 exporter指向不存在或者不能訪問(non-accessible)的JAR包 exporter指向不存在或者不能實例化(non-instantiable)的類 exporter實例在Exporter#configure方法拋異常
這意味著,對于每個分區(qū)的exporter,只會有且只有一個實例:如果有4個分區(qū),并且有至少4個線程處理記錄,那么可能有4個exporter實例同時在導(dǎo)出記錄。
在raft故障轉(zhuǎn)移再處理(reprocessing)過程中(例如:選舉新的leader) 偏移位沒有更新出錯
注意:雖然Zeebe盡力保證減少exporter處理的重復(fù)記錄數(shù),但是還是會出現(xiàn)重復(fù)記錄,因此,有必要保證export操作的冪等性。可以在exporter代碼中實現(xiàn)冪等性,但是如果導(dǎo)出到外部系統(tǒng)中,推薦在外部系統(tǒng)中做去重,這樣降低Zeebe的負載。
四、上手體驗



