2013-02-14 47 views
4

說我有一個多步驟的,異步處理與這些限制:如何構建使用消息隊列的多步驟流程?

  1. 各個步驟可以通過任何工人
  2. 步驟必須執行來執行有序

該方法I」 m考慮:

  1. 插入表示整個過程的db行,並使用「Steps completed」列來跟蹤進度。
  2. 訂閱將在整個過程完成時接收消息的隊列。
  3. 完成每個步驟後,請更新數據庫行並對流程中的下一個步驟進行排隊。
  4. 最後一步完成後,排隊「進程已完成」消息。
  5. 刪除數據庫行。

想法?陷阱?更智能的方法來做到這一點?

回答

7

我已經構建了一個與您在大型任務密集型文檔處理系統中描述的系統非常相似的系統,並且在過去的7年中不得不同時考慮利弊。你的方法是堅實的,可行的,但我看到一些缺點:

  • 可能受到狀態改變(即,如果過程輸入改變所有的步驟都排隊等待,那麼後面的步驟可能有輸入與前面的步驟不一致)

  • 更多的基礎設施比你想,同時涉及一個DB和隊列=失敗的多點,難以成立,更需要的文件=並不完全感覺不對

  • 你如何讓多名工人同時採取同一步驟?換句話說,DB行表示完成了4個步驟,工作流程如何知道它是否可以採用#5?它不需要知道另一個進程是否已經在處理這個問題?這種或那種方式(DB或MQ)需要包含額外的鎖定狀態。

  • 您的示例對失敗很有效,但沒有解決併發問題。當你添加狀態來解決併發問題時,故障處理就成了一個嚴重的問題。例如,一個進程執行第5步,然後將DB行放入「Working」狀態。然後,當該過程失敗時,步驟5卡在「工作」狀態。

  • 您的編排器有點沉重,因爲它正在做很多同步數據庫操作,我擔心它可能無法像其他體系結構那樣擴展,因爲只能有一個。 ..這將取決於你的步驟與數據庫事務相比有多長 - 這可能只會成爲一個非常大規模的問題。

如果我再做一遍,我肯定會把更多的編排推到工作進程上。所以,編制代碼很常見,可以由任何工作進程調用,但我會盡可能保持中央控制過程的輕鬆。我也只使用消息隊列而不使用任何數據庫來保持體系結構的簡單性和較少的同步性。

我將創建2個隊列交換:IN和WIP(工作正在進行中)

中心進程負責訂閱處理請求,並檢查WIP隊列超時步驟。

1)當中央處理接收到用於給定的處理(X)的請求時,它調用編排碼,並將其加載第一個任務(X1)到IN隊列

2)第一可用的工作進程(P1)事務性地使X1出隊,並將其排入WIP隊列,並具有保守的生存時間(TTL)超時值。這個出隊是原子的,IN中沒有其他X任務,所以沒有第二個進程可以在X任務上工作。 3)如果P1突然終止,地球上沒有任何體系結構可以保存這個過程,除了超時之外。在超時期結束時,中央進程將在WIP中發現超時X1,並且將事務性地將WIP中的X1出隊並將其排入IN,從而提供適當的通知。 4)如果P1異常但優雅地終止,那麼工作進程將事務性地將X1從WIP中出列並將其排入IN,並提供適當的通知。根據例外情況,工作進程也可以選擇重置TTL並重試該步驟。 5)如果P1無限期地掛起,或者超過TTL,則結果與#3相同。中央進程處理它,並且大概工作進程將在某個時候被回收 - 或者規則可以是在任何時候超時的情況下回收工作進程。 6)如果P1成功,則工作進程將確定下一步,即X2或X-done。如果下一步是X2,那麼工作進程將事務性地從WIP中出列X1,並將X2排入IN。如果下一步是X-done,那麼處理完成,並且可以採取適當的操作,也許這會將X-done排入IN以供管理員隨後處理。

我建議的方法的好處是:

  • 工作進程之間的爭指定

  • 所有可能的故障情況(崩潰,異常,掛起和成功)的處理

  • 簡單的架構可以完全用RabbitMQ實現,並且沒有數據庫,這使得它更具可擴展性

  • 由於工人處理決定和進行排隊,下一步,還有一個更輕量級的配器,導致更可擴展的系統

的唯一缺點是,它可能會遭受的狀態變化,但通常這是不值得擔心。只有您可以知道這是否會成爲您系統中的問題。

我對此的最終想法是:您應該有充分的理由進行這種編排。畢竟,如果進程P1完成任務X1,現在是某個進程處理下一個任務X2的時間,看起來P1將是一個非常好的候選人,因爲它剛剛完成X1並且現在可用。通過這個邏輯,一個過程應該貫穿所有步驟直到完成 - 爲什麼混合和匹配過程如果任務需要連續完成?唯一的異步邊界確實是在客戶端和工作進程之間。但是我會假設你有一個很好的理由來執行此操作,例如,這些進程可以運行在不同的和/或資源專用的機器上。

+0

EXCELLENT answer,J.T.非常感謝;我一定會採取你在這裏建議的方法。 – marclar 2013-02-14 15:27:32

+0

附加問題:您將如何處理稍後排隊的任務?存儲在一個分貝,直到他們準備好排隊?這是我目前的計劃。 – marclar 2013-02-14 16:08:54

+1

是的,我認爲是的。儘管試圖將未來的任務放入MQ中是件很誘人的事情,但它與消息隊列的語義不一致 - 例如,在某些時候,您必須在隊列中的特定位置插入任務。這感覺就像是在數據庫層次上做得更恰當一些,然後你就有了緊密的語義,主動準備處理的任務在隊列中,而那些不在DB中的任務。 – 2013-02-14 16:46:21