<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 11066字,需瀏覽 23分鐘

           ·

          2021-03-26 20:17

          導(dǎo)語 | 微服務(wù)架構(gòu)的一大核心是把大的復(fù)雜的業(yè)務(wù)系統(tǒng)拆分成高內(nèi)聚的微服務(wù),每個服務(wù)負責(zé)相對獨立的邏輯。服務(wù)拆分的好處無需贅述,但是要實現(xiàn)業(yè)務(wù)價值,不是看單個服務(wù)的能力,而是要協(xié)調(diào)所有服務(wù)保證企業(yè)端到端業(yè)務(wù)流的成功。那么,誰來負責(zé)端到端業(yè)務(wù)流的成功呢?在調(diào)研工作流引擎的過程中,筆者了解到微服務(wù)編排模式及微服務(wù)編排引擎Zeebe,可以很好的回答這個問題。文章作者:唐炯,騰訊CSIG研發(fā)工程師。


          一、工作流與微服務(wù)編排



          1. 工作流


          提到工作流,印象里都是OA系統(tǒng)各種請假審批流。事實上,廣義上的工作流是對工作流程及其各操作步驟之間業(yè)務(wù)規(guī)則的抽象、概括、描述。簡單理解,我們為了實現(xiàn)某個業(yè)務(wù)目標(biāo),抽象拆解出來的一系列步驟及這些步驟之間的協(xié)作關(guān)系,就是工作流。例如訂單發(fā)貨流、程序構(gòu)建流等。業(yè)界通常用BPMN流程圖來描述一個工作流。

          (1)沒有工作流時的任務(wù)協(xié)作

              
          以實現(xiàn)一個用戶購買邏輯為例,如果不應(yīng)用工作流模型,我們串聯(lián)多個任務(wù)(步驟)一般是通過顯示的代碼調(diào)用:

              
          校驗、支付、發(fā)貨一氣呵成,流暢自然。正喝著枸杞紅棗,產(chǎn)品一臉笑意跑過來:“我們新搞個充會員卡的業(yè)務(wù),大概步驟就校驗 -> 推薦 -> 支付 -> 充值。校驗和支付前面都做過了,應(yīng)該很快實現(xiàn)吧?”

          精通if-else的你,聽完的瞬間就已經(jīng)構(gòu)思好了代碼:

              
          一通寫下來,總感覺哪里不對,“為什么加新的任務(wù)節(jié)點,要改已有的代碼呢?這不符合開閉原則啊!”。

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

              
          工作流模型正是為了解決這類問題而生:分離任務(wù)的實現(xiàn)和任務(wù)的協(xié)作關(guān)系。上面同樣的用戶購物邏輯,有了工作流模型,各個任務(wù)只實現(xiàn)自己原子的邏輯,任務(wù)協(xié)作關(guān)系使用流程圖來表達。

              
          當(dāng)新的邏輯需要復(fù)用已有任務(wù)節(jié)點時,只需要調(diào)整流程圖,無需修改已有代碼。


          2. 工作流引擎

              
          將任務(wù)實現(xiàn)與任務(wù)協(xié)作關(guān)系分離之后,就誕生了專門維護任務(wù)協(xié)作關(guān)系的程序 - 工作流引擎(也常稱作流程引擎)。

              
          其中最具有代表性的就非Activiti莫屬了。在企業(yè)應(yīng)用蓬勃發(fā)展的21世紀(jì)初,它幾乎是實現(xiàn)流程自動化的標(biāo)配。關(guān)于Activiti的介紹,網(wǎng)上已經(jīng)有足夠多的文章。今天我們要介紹是由Activiti的核心成員打造的另一款專為微服務(wù)編排而生的工作流引擎 -  Zeebe。在開始之前,我們先理解下什么是微服務(wù)編排。

          3. 微服務(wù)編排

              
          微服務(wù)架構(gòu)的一大核心是把大的復(fù)雜的業(yè)務(wù)系統(tǒng)拆分成高內(nèi)聚的微服務(wù),每個服務(wù)負責(zé)相對獨立的邏輯。例如一個電商系統(tǒng),可能會拆分出支付微服務(wù)、訂單微服務(wù)、倉儲微服務(wù)、物流微服務(wù)等。服務(wù)拆分的好處無需贅述,但是要實現(xiàn)業(yè)務(wù)價值,不是看單個服務(wù)的能力,而是要協(xié)調(diào)所有服務(wù)保證企業(yè)端到端業(yè)務(wù)流的成功。

          那么,哪個服務(wù)來負責(zé)端到端業(yè)務(wù)流的成功呢?答案是沒有。事實上,在公司內(nèi),端到端的業(yè)務(wù)流可能都沒有正式的文檔說明,從一個微服務(wù)到另一個微服務(wù)的事件流轉(zhuǎn)都是在代碼里隱式表達的。
              
          很多微服務(wù)架構(gòu)依賴一種相對純粹的編舞模式(choreography pattern)來解決這個問題。在這種模式下,微服務(wù)通過向一個消息隊列發(fā)送和接收事件來相互協(xié)作。編舞模式給開發(fā)者提供了很高的靈活度,但是編舞模式仍不能解決:

          • 可見性:多少端到端業(yè)務(wù)流正在運行中,它們的狀態(tài)是什么樣子。過去24小時,有多少業(yè)務(wù)流實例沒有成功結(jié)束?為什么這些業(yè)務(wù)流實例沒有成功結(jié)束?一個業(yè)務(wù)流或者某個任務(wù)完成的平均時間是多少?

          • 異常處理:如果業(yè)務(wù)流里有一個微服務(wù)失敗,誰負責(zé)處理這個異常?業(yè)務(wù)流的重試邏輯是怎么樣的?如果需要人工介入,問題的升級處理規(guī)則是怎么樣的?

              
          于是便誕生了一種更嚴(yán)格的編排模式(orchestration pattern),用于協(xié)調(diào)各個微服務(wù)。在這種模式下,會有一個中控的引擎:

          • 按照業(yè)務(wù)邏輯的藍圖,編排各個微服務(wù)的調(diào)用關(guān)系;

          • 監(jiān)控整個業(yè)務(wù)流的狀態(tài);

          • 提供自動化的機制處理單個服務(wù)的失敗,保證整個業(yè)務(wù)流的成功。

              
          可以借用下面的圖,來進一步理解微服務(wù)編排和微服務(wù)編舞模式的區(qū)別:

              
          按照我們前面對工作流模型的闡述,工作流引擎很適合作為中控引擎,來編排調(diào)度微服務(wù)。那為什么諸如Activiti等傳統(tǒng)的工作流引擎沒能繼續(xù)占領(lǐng)微服務(wù)編排的市場,而是誕生了新的微服務(wù)編排引擎-Zeebe?更有趣的是,Zeebe的核心開發(fā),也是來自最初的Activiti團隊。
              
          答案是諸如Activiti等傳統(tǒng)工作流引擎的架構(gòu)無法適應(yīng)當(dāng)下微服務(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在設(shè)計之初,就考慮到了這些問題,下文來為大家詳細介紹。


          二、Zeebe特性與頂層架構(gòu)



          1. Zeebe核心特性

              
          Zeebe是專為微服務(wù)編排設(shè)計的免費開源的工作流引擎,它提供了:

          • 可見性(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)的重試或者升級給運維團隊手動處理,確保工作流總是能按計劃完成。


          Zeebe設(shè)計之初,就考慮了超大規(guī)模的微服務(wù)編排問題。為了應(yīng)對超大規(guī)模,Zeebe支持:

          • 橫向擴容(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)


          Zeebe架構(gòu)主要包含4大組件:client, gateway, brokers 以及 exporters.


          (1)Client


          客戶端向Zeebe發(fā)送指令:

          • 發(fā)布工作流(deploy workflows)

          • 執(zhí)行業(yè)務(wù)邏輯(carry out business logic)

                 -創(chuàng)建工作流實例(start workflow instances)
                 -發(fā)布消息(publish messages)
                 -激活任務(wù)(activate jobs)
                 -完成任務(wù)(complete jobs)
                 -失敗任務(wù)(fail jobs)
          • 處理運維問題(handle operational issues)
                 -更新實例流程變量(update workflow instance variables)
                 -解決異常(resolve incidents)

          客戶端程序可以完全獨立于Zeebe擴縮容,Zeebe brokers不執(zhí)行任何業(yè)務(wù)邏輯。客戶端是嵌入到應(yīng)用程序(執(zhí)行業(yè)務(wù)邏輯的微服務(wù))的庫,用于跟Zeebe集群連接通信。客戶端通過基于HTTP/2協(xié)議的gRPC與Zeebe gateway連接。

          Zeebe官方提供了Java和Go客戶端。社區(qū)提供了C#,Ruby,JavaScript客戶端實現(xiàn)。gRPC協(xié)議很方便生成其他語言的客戶端。

          Client中,執(zhí)行單獨任務(wù)的單元叫JobWorker。

          (2)Gateway

          Gateway作為Zeebe集群的入口,轉(zhuǎn)發(fā)請求到brokers。Gateway是無狀態(tài)(stateless)無會話(sessionless)的,可以按需增加節(jié)點,以負載均衡及高可用。

          (3)Broker

          Broker是分布式的流程引擎,維護運行中流程實例的狀態(tài)。Brokers可以分區(qū)以實現(xiàn)橫向擴容、副本以實現(xiàn)容錯。通常情況下,Zeebe集群都不止一個節(jié)點。

          需要重點強調(diào)的是,broker不包含任何業(yè)務(wù)邏輯,它只負責(zé):

          • 處理客戶端發(fā)送的指令
          • 存儲和管理運行中流程實例的狀態(tài)
          • 分配任務(wù)給job workers


          Brokes形成一個對等網(wǎng)絡(luò)(peer-to-peer),這樣集群不會有單點故障。集群中所有節(jié)點都承擔(dān)相同的職責(zé),所以一個節(jié)點不可用后,節(jié)點的任務(wù)會被透明的重新分配到網(wǎng)絡(luò)中其他節(jié)點。

          (4)Exporter

          Exporter系統(tǒng)提供Zeebe內(nèi)狀態(tài)變化的事件流。這些事件流數(shù)據(jù)有很多潛在用處,包括但不限于:

          • 監(jiān)控當(dāng)前運行流程實例的狀態(tài)
          • 分析歷史的工作流數(shù)據(jù)以做審計或BI
          • 跟蹤Zeebe拋出的異常(incident)


          Exporter提供了簡潔的API,可以流式導(dǎo)出數(shù)據(jù)到任何存儲系統(tǒng)。Zeebe官方提供開箱即用的Elasticsearch exporter,社區(qū)也提供了其他Exporters。


          三、Zeebe內(nèi)部核心實現(xiàn)



              
          Zeebe能做到高吞吐、高可用的微服務(wù)編排,得益于三個關(guān)鍵實現(xiàn):

          1. 分布式
              
          Zeebe設(shè)計之初就考慮了分布式部署,可以在不依賴外部組件的情況下,搭建一個Zeebe broker集群,集群中節(jié)點組成一個對等的網(wǎng)絡(luò)(peer-to-peer network)。在網(wǎng)絡(luò)中,所有的節(jié)點都有相同的職責(zé),保證集群不會有單點故障。

          Zeebe內(nèi)部抽象了一個只追加寫的隊列(可以類比理解成kafka的topic),來處理和存儲數(shù)據(jù)。當(dāng)集群有多個broker節(jié)點時,會將隊列劃分成多個分區(qū)(partitions,或者分片shards),分布到各個節(jié)點上。每個分區(qū)有多個副本(replicas)。在所有的副本中,會根據(jù)raft協(xié)議選出一個leader,leader負責(zé)接收請求和執(zhí)行所有處理邏輯。其他broker上的副本就是被動的跟隨者(passive followers)。當(dāng)leader不可用時,followers會透明地選出新的leader。


          2. 消息驅(qū)動
              
          Zeebe消息驅(qū)動架構(gòu),體現(xiàn)在兩個方面:

          • Zeebe Broker內(nèi)部使用隊列(即LogStream,只追加寫),異步處理請求;
          • Zeebe JobWorker和Broker使用發(fā)布訂閱的模式交互,當(dāng)工作流任務(wù)狀態(tài)發(fā)生變化,Broker會發(fā)布相應(yīng)事件。JobWorker通過輪詢的方式,訂閱處理自己相關(guān)的事件。


          (1)Broker內(nèi)部流處理模型
              
          Zeebe內(nèi)部實現(xiàn),其實就是一系列作用在記錄流(record streams)上的流處理器(stream processors)。流處理模型作為一個統(tǒng)一的實現(xiàn)方式,提供:

          • 指令協(xié)議(command protocol,即請求響應(yīng))
          • 記錄導(dǎo)出(record export / streaming)
          • 工作流演算(evaluation, 異步后臺任務(wù))



          a. 狀態(tài)機(state machines)
              
          Zeebe管理有狀態(tài)的實體:任務(wù)、工作流實例等。在內(nèi)部,這些實體實現(xiàn)為流處理器管理的狀態(tài)機。狀態(tài)機模式的概念很簡單。一個狀態(tài)機的實例總是處于某個邏輯狀態(tài)。對于每一個狀態(tài),一系列轉(zhuǎn)換(transitions)定義了下一步可能的狀態(tài)。轉(zhuǎn)換到下一個新狀態(tài)可能產(chǎn)生輸出或者副作用(side effects)。

          如下圖是任務(wù)(jobs)的狀態(tài)機:


          橢圓代表狀態(tài),箭頭代表狀態(tài)轉(zhuǎn)換。要注意的是,狀態(tài)轉(zhuǎn)換只能用在特定的狀態(tài)上。比如,不能在任務(wù)處于CREATED狀態(tài)的時候完成(complete)任務(wù)。

          b. 事件和指令(events and commands)
              
          狀態(tài)機里的每個狀態(tài)變化被稱為事件(event)。Zeebe會把每個事件當(dāng)成一條記錄發(fā)布到流上。狀態(tài)變化可以通過發(fā)送指令觸發(fā)。Zeebe broker從兩個源頭接收指令:

          • 客戶端發(fā)送指令。例如:發(fā)布工作流、啟動流程實例、創(chuàng)建和完成任務(wù)等;
          • broker自身產(chǎn)生指令。例如:查找可以被worker執(zhí)行的任務(wù)。


          指令一旦接收到,就會被當(dāng)做記錄寫到流里。

          c. 有狀態(tài)的流處理(stateful stream processing)

          流處理器從流里有序地讀取記錄,然后根據(jù)記錄關(guān)聯(lián)的實體的生命周期,解析指令。流處理器循環(huán)的執(zhí)行下面的步驟:

          1. 從流里消費指令(command)
          2. 根據(jù)狀態(tài)生命周期和實體當(dāng)前狀態(tài),判斷指令是否適用
          3. 如果指令適用,應(yīng)用到狀態(tài)機。如果指令是客戶端發(fā)送的,發(fā)送回響應(yīng)。
          4. 如果指令不適用,拒絕。如果是客戶端發(fā)過來的,發(fā)送錯誤響應(yīng)信息。
          5. 發(fā)布新的事件,報告實體新的狀態(tài)。


          例如:處理Create Job指令,會產(chǎn)生Job Created事件。

          d. 指令觸發(fā)器(command triggers)

          一個實體的狀態(tài)變化可以自動觸發(fā)針對另一個實體的指令。例如:當(dāng)一個任務(wù)完成了,相應(yīng)的流程實例應(yīng)該繼續(xù)后續(xù)的任務(wù),也就是說,Job Completed事件觸發(fā)了Complete Activity指令。

          e. 處理背壓(handling back-pressure)
              
          當(dāng)broker收到客戶端請求,會先把請求寫到事件流里,然后交由流處理器處理。如果處理太慢或者流里面堆積了太多客戶端請求,處理器可能需要花很長時間才能處理新接收到的請求指令。如果broker繼續(xù)從客戶端接收新請求,待處理的任務(wù)(back log)會不斷增加,任務(wù)處理延時會超過可以接收的時間。為了避免這種問題,Zeebe采用了一種背壓機制。當(dāng)broker接收到的請求超過其能在一定延時范圍內(nèi)處理的限度,broker就會拒絕(reject)一些請求。
              
          broker能處理的最大請求速率取決于機器的處理能力、網(wǎng)絡(luò)延時、系統(tǒng)的當(dāng)前負載等。因此,Zeebe不會配置固定的最大請求限度。相反的,Zeebe采用自適應(yīng)的算法動態(tài)的決定inflight(broker已經(jīng)接收但是還沒處理完成的)請求數(shù)限度。當(dāng)新的請求被接收時,Inflight請求數(shù)增加;當(dāng)請求處理完成,響應(yīng)發(fā)回給客戶端后, Inflight請求數(shù)減少。當(dāng)Inflight請求數(shù)達到限度,broker拒絕后續(xù)的請求。
              
          如果broker因為背壓拒絕了客戶端請求,客戶端可以用合適的重試策略重試。如果拒絕率一直很高,說明broker持續(xù)處于高負載。在這種情況下,推薦降低請求速率。

          (2)Broker和JobWorker發(fā)布訂閱模式
              
          業(yè)務(wù)微服務(wù)集成Zeebe client SDK,針對每個JobType,創(chuàng)建一個JobWorker,在JobWorker里實現(xiàn)業(yè)務(wù)邏輯。JobWorker的創(chuàng)建很簡單,以Java SDK為例,在普通的Java方法上添加一個注解即可。

          @Component@Slf4j
          public class SomeJob { @EnhancedJobWorker(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("失敗原因"); }}
           
          與Activiti引擎主動調(diào)用業(yè)務(wù)handler的模式不同,JobWorker創(chuàng)建之后,內(nèi)部會啟動一個輪詢線程JobPoller,定期(默認(rèn)100ms)從Broker輪詢自己相關(guān)的事件(job created)。

              
          拿到Broker端返回的任務(wù)后,會把任務(wù)信息傳入業(yè)務(wù)邏輯Handler里執(zhí)行。整個時序如下圖:

              
          Zeebe客戶端主動輪詢的模型,進一步解耦了引擎任務(wù)狀態(tài)維護和微服務(wù)業(yè)務(wù)處理邏輯,可以讓業(yè)務(wù)JobWorker根據(jù)自己的處理能力,以相對恒定的速率處理任務(wù)。當(dāng)短時間內(nèi)有大量任務(wù)創(chuàng)建時,Broker的隊列模型,可以堆積任務(wù),平滑流量。

          3. 運行時數(shù)據(jù)和歷史數(shù)據(jù)分離
              
          當(dāng)Zeebe處理任務(wù)、工作流或者內(nèi)部維護時,會產(chǎn)生有序的記錄流:

              
          雖然客戶端沒辦法直接審查流,但是Zeebe可以用exporter的方式,加載和配置用戶代碼處理每條記錄。exporter提供了統(tǒng)一的入口處理寫到流里的記錄:

          • 通過把歷史數(shù)據(jù)推到外部數(shù)據(jù)倉庫中,持久化歷史數(shù)據(jù)
          • 把記錄導(dǎo)出到可視化工具中(例如: zeebe-simple-monitor)

              
          Zeebe只會裝載通過Zeebe YAML配置文件配置的exporters。exporter配置好后,會在Zeebe下次啟動的時候,開始接收記錄。需要注意的是,也只能保證接收到從那以后的數(shù)據(jù)。exporter最大的作用是可以減少Zeebe集群無限存儲數(shù)據(jù)的壓力。當(dāng)Zeebe不再需要某些數(shù)據(jù)時,會先查詢exporters看是否可以安全刪除這些數(shù)據(jù),如果可以,就會永久的刪除這些數(shù)據(jù),因此可以減少集群磁盤占用。不管exporter怎么裝載(是否通過外部jar包),所有的exporters都同樣的以Exporter interface定義的方式與broker交互。

          (1)裝載(Loading)
              
          exporter配置好后,會在broker的啟動階段裝載。在裝載階段,會去校驗每個exporter的配置,如果有下面的問題,broker會啟動失敗:

          • exporter id不唯一
          • exporter指向不存在或者不能訪問(non-accessible)的JAR包
          • exporter指向不存在或者不能實例化(non-instantiable)的類
          • exporter實例在Exporter#configure方法拋異常


          (2)處理(Processing)
              
          在任何時候,對于某個partition,只會有一個主節(jié)點(leader node)。當(dāng)節(jié)點變成某個partition的leader時,它要做的事情之一就是運行一個exporter stream processor實例。這個流處理器,會給每個配置好的exporter創(chuàng)建一個實例,然后把每條記錄都轉(zhuǎn)發(fā)到這些exporter實例上。

          這意味著,對于每個分區(qū)的exporter,只會有且只有一個實例:如果有4個分區(qū),并且有至少4個線程處理記錄,那么可能有4個exporter實例同時在導(dǎo)出記錄。

          注意Zeebe只保證至少一次(at-least-once)的語義,也就是說,一條記錄至少會被一個exporter看到一次,可能會多次。在這些情況下,可能會重復(fù):

          • 在raft故障轉(zhuǎn)移再處理(reprocessing)過程中(例如:選舉新的leader)
          • 偏移位沒有更新出錯

              
          為了減少exporter處理的重復(fù)記錄數(shù),流處理器會記錄每個exporter最新成功導(dǎo)出的記錄的偏移位置(position)。有這個偏移位就足夠了,因為流是有序的記錄序列,在流中,偏移位(position)是單調(diào)遞增的。這個偏移位是當(dāng)exporter保證記錄被成功導(dǎo)出后,exporter去更新維護的。

          注意:雖然Zeebe盡力保證減少exporter處理的重復(fù)記錄數(shù),但是還是會出現(xiàn)重復(fù)記錄,因此,有必要保證export操作的冪等性。可以在exporter代碼中實現(xiàn)冪等性,但是如果導(dǎo)出到外部系統(tǒng)中,推薦在外部系統(tǒng)中做去重,這樣降低Zeebe的負載。

          (3)錯誤處理(Error handling)
              
          如果錯誤出現(xiàn)在Exporter#open(Context)階段,流處理器會失敗然后重啟修復(fù)錯誤。最壞的情況是,在錯誤修復(fù)前,沒有exporter運行。

          如果錯誤出現(xiàn)在Exporter#close階段,錯誤信息會被記錄到日志里,仍會保證其他exporter優(yōu)雅完成工作。

          如果錯誤出現(xiàn)在處理階段,會無限重試同一條記錄,直到不再產(chǎn)生錯誤。最壞的情況是,一個失敗的exporter會導(dǎo)致其他exporters掛起。當(dāng)前,需要exporter實現(xiàn)自己的重試/錯誤處理策略,后續(xù)可能改變。

          (4)性能影響(Performance impact)

          對于每個裝載的exporter,Zeebe自然會帶來一些性能影響。對于某個partition,一個慢的exporter會導(dǎo)致其他exporter也變慢,最壞的情況下,會完全阻塞住一個線程。因此推薦exporter的邏輯盡可能的簡單,把數(shù)據(jù)增強和轉(zhuǎn)換等邏輯都放在外部系統(tǒng)中。

          四、上手體驗



          Zeebe作為Camunda公司的一個子項目,從2017年開始,獨立開源運作。Camunda公司核心團隊來自于早期的Activiti團隊,主營以Activiti為核心的工作流咨詢服務(wù)。從今年3月開始,Camunda宣布打包Zeebe引擎、控制臺Operate、建模工具等提供SaaS服務(wù),但核心的流程引擎Zeebe仍然以開源的方式迭代。
             
          Zeebe不依賴外部組件,可以使用本地jar包、Docker等快速搭建集群環(huán)境【1】。參考官方指引【2】可以快速創(chuàng)建Demo項目。
            
          官方給出的benchmark【3】,8核32G單節(jié)點4分區(qū)1副本的配置下,能達到3.2w instance/s的性能。而且增加Broker節(jié)點,基本可以線性提高處理能力。

             
          在我們實際6個8C 16G的SKTE POD集群中,使用WeTest壓測大師壓測到了 3w instance/s的性能(每個流程2個節(jié)點,包含大約50個流程變量)。與官方數(shù)據(jù)有一定差距,受限于官方benchmark環(huán)境和配置給的不全,沒辦法完全模擬。看資源瓶頸主要在磁盤IO上。但這個數(shù)據(jù)相對我們之前Activiti 5~6 k instance/s就崩潰來說,已經(jīng)是很大提升了。
             
          另一方面,Zeebe還處于早期的迭代階段,穩(wěn)定性和功能完整度都還在持續(xù)優(yōu)化中。目前支持到BPMN的ServiceTask任務(wù),同時在任務(wù)調(diào)度上,也有小概率的miss掉任務(wù)的情況。但從一開始的架構(gòu)設(shè)計、場景定位、社區(qū)活躍度等方面來看,是可以期待的項目。

          立個flag,接下來筆者還會持續(xù)輸出Zeebe內(nèi)部實現(xiàn)的深入分析文章。分布式、異步化、Actor線程模型這些套路的實現(xiàn)還是很值得學(xué)習(xí)的。也歡迎對微服務(wù)編排、流程引擎感興趣的同學(xué)拍磚交流~

          參考鏈接:

          [1] 快速搭建集群環(huán)境指引:
          https://docs.camunda.io/docs/product-manuals/zeebe/deployment-guide/index/
          [2快速創(chuàng)建Demo項目:
          https://docs.camunda.io/docs/guides/setting-up-development-project/
          [3官方benchmark:
          https://camunda.com/blog/2019/08/zeebe-horizontal-scalability/
          [4Zeebe官方倉庫:
          https://github.com/camunda-cloud/zeebe
          [5Zeebe官方文檔:
          https://docs.camunda.io/docs/product-manuals/zeebe/zeebe-overview
          [6Zeebe問答社區(qū):
          https://forum.camunda.io/

          瀏覽 175
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩成人无码一区二区视频 | 美日韩一级 | 日本无码片 | 日本黄色性爱视频 | 色第一页|