uber/cadence:Cadence是一種分散式,可擴充套件,持久且高度可用的流程編排引擎

banq發表於2019-09-13

定位類似zeebe、activiti之類工作流引擎,高階別的區別在於zeebe是基於BPMN的,Cadence支援使用Java或Go等普通程式語言編寫編排程式碼。大多數複雜程式都不是使用視覺化程式設計編寫的。它只是不適用於複雜的用例。學習Cadence程式設計也更簡單,因為您只需要學習一些編寫Java(或其他)程式碼的規則。BPMN更具限制性和複雜性。
系統架構方式存在很多技術差異。Cadence依賴於分割槽資料庫。目前支援MySQL和Cassandra,未來還會有更多支援。Zeebe使用 EventSourcing,寫入吞吐量更大。
Cadence文件很晦澀難懂,這也是Uber大裁員的一個原因吧,不使用業內通用模式和架構,自己建立一套,但是需要首先說明自己這套相比通用的有什麼缺點和優點,直接上來闡述功能,怪不得被人比喻成類似奧斯卡頒獎禮儀。
它的大概原理是:
業務邏輯被建模為“工作流workflow”和“活動activities”。“工作流workflow”是業務協調邏輯的實現,其唯一目的是協調“活動activities”執行。“活動activities”是用於實現業務邏輯的任務。
“工作流workflow”和“活動activities”的實現是在工作程式中託管和執行。這些工作者長期輪詢Cadence伺服器以執行任務,透過呼叫“工作流workflow”和“活動activities”實現來執行任務,並將任務結果返回給Cadence伺服器。此外,工作人員可以實現為完全無狀態的服務,這反過來允許無限制的水平擴充套件。

有的企業已經開始應用Cadence了,他們的體驗如下:
我們已經將Cadence投入生產近一年了。我們將其用於雲提供商的基礎架構配置。
第一個POC在兩週內準備就緒,再過兩個星期我們將其推向生產階段。最初的學習曲線相當高,因為Cadence的構建工作流程起初並不一定容易(當時我們開始時沒有太多的文件),但之後它更容易。
相關部落格:https://banzaicloud.com/tags/cadence/
市場上有各種不同的任務佇列(我不是在開玩笑,你可以自己在taskqueues.com上檢視它們),那麼是什麼讓Cadence出類拔萃呢?是什麼讓它成為一個複雜的分散式任務佇列管理器?首先,您可以在程式碼中定義工作流程,讓Cadence處理狀態,超時,歷史記錄和所有其他必需品。然後,可以在提交後檢查這些工作流程,以便您可以檢查其進度和結果,或根據需要向其傳送外部訊號。

uber/cadence:Cadence是一種分散式,可擴充套件,持久且高度可用的流程編排引擎Matching Service是負責分派任務,保證了at-most-once語義,這意味著工作流的每個活動要麼只執行一次,要麼(在失敗的情況下)根本不執行。
History Service是神奇魔力所在。它管理佇列,處理事件,儲存和改變工作流狀態。
您必須編寫的程式碼:

  • 定義”工作流workflow”並執行“活動activities”的實際任務的工作者worker,
  • 用於提交工作流程執行請求的程式碼,以及
  • 可選擇檢查”工作流workflow”進度或結果。

與Activities工作流程的可重用構建塊(保證最多執行一次)不同,”工作流workflow”程式碼會重複執行多次。雖然您可以自由地按照自己喜歡的方式組織工作流程式碼,並且可以安全地使用Go的控制結構和純函式(即沒有副作用的那些),但必須確保您的”工作流workflow”具有確定性。要實現這一點,您應該使用Cadence提供的特殊功能,而不是具有副作用的構造或依賴於某些外部狀態的構造,如資料庫,熵源或掛鐘時間。我們更喜歡將大多數變數重新定位為工作流引數,而不是在執行期間查詢它們。
不要忘記,對於“活動activities”沒有這些的限制,可以在執行較長時間的程式中使用適當的Go構造。當然,您不應洩漏資源或在程式碼中啟動無人參與的Go例程。另一方面,您必須在自己的工作流程式碼中處理失敗和重新執行活動,這在冪等活動中通常更容易。

在Cadence”工作流workflow”中執行“活動activities”

// Synchronous activity execution
workflow.ExecuteActivity(ctx, sendEmailActivity).Get(ctx, &result)

// Asynchronous activity execution
future := workflow.ExecuteActivity(ctx, sendEmailActivity)


執行Go例程

// Cadence
workflow.Go(ctx, func(ctx workflow.Context) {/* … */})

// Plain Go
go func(ctx context.Context) {/* … */}(ctx)


建立channel,傳送和接收資料

// Cadence
channel := workflow.NewChannel(ctx)
channel.Send(ctx, true)
channel.Receive(ctx, &result)

// Plain Go
channel := make(chan interface{})
channel <- true
result := <-channel


建立可取消的上下文:

// Cadence
childCtx, cancelHandler := workflow.WithCancel(ctx)

// Plain Go
childCtx, cancelHandler := context.WithCancel(ctx)



計時器:

// Cadence
workflow.NewTimer(childCtx, processingTimeThreshold)

// Plain Go
timer.NewTimer(processingTimeThreshold)


sleep:

// Cadence
workflow.Sleep(sleepTime)

// Plain Go
time.Sleep(sleepTime)


等待完成一項行動:

// Cadence
selector := workflow.NewSelector(ctx)
selector.AddFuture(future, handle)
selector.Select(ctx)

// Plain Go
select {    
  case <-ready: handle()        
  case <-ctx.Done():
}


在K8s上可以安裝Cadence,見部落格文件,點選標題進入原文

相關文章