協(xié)調一系列在分布式服務集和其他遠程資源的的行為,試圖透明地處理故障,如果這些操作失敗,或撤銷,如果系統(tǒng)不能從故障中恢復執(zhí)行工作的影響。這種模式可以分布式系統(tǒng)中增加彈性和靈活性,使之恢復和重試失敗是由于短暫的異常,持久的故障和處理故障等操作。
應用程序執(zhí)行其包括多個步驟,其中的一些可以調用遠程服務或訪問遠程資源的任務。各個步驟可以是相互獨立的,但它們是由實現(xiàn)該任務的應用程序邏輯編排。
只要有可能,應用程序應該確保任務運行完成和解決遠程訪問服務或資源時可能發(fā)生的任何故障??赡軙蚋鞣N原因,這些故障。例如,該網(wǎng)絡可能是崩潰,通信可能被中斷,遠程服務可能停止響應或處于不穩(wěn)定的狀態(tài),或遠程資源可能暫時無法訪問,可能由于資源約束。在許多情況下,這些故障可能是暫時的,并且可以通過使用重試模式進行處理。
如果該應用程序檢測到一個更永久的故障,從它可以不容易恢復,它必須能夠將系統(tǒng)恢復到一致狀態(tài),并確保整個端至端的操作的完整性。
調度代理管理者模式定義了以下角色。這些演員編排的步驟(工作,單個項目)將作為任務(整個過程)的一部分進行:
注意: 調度程序執(zhí)行類似的功能,以在流程管理模式的過程管理器。實際工作流程通常被定義并通過由該調度器所控制的工作流引擎來實現(xiàn)。這種方法分離了業(yè)務邏輯從調度的工作流程。
調度程序,代理和管理者是邏輯組件和它們的物理實現(xiàn)取決于所使用的技術。例如,若干個邏輯代理可以被實現(xiàn)為一個單一的網(wǎng)絡服務的一部分。
調度器維護關于任務的進度和持久的數(shù)據(jù)存儲中的每個步驟中,被稱為狀態(tài)存儲的狀態(tài)信息。主管可以使用此信息來幫助確定一個步驟是否出現(xiàn)故障。圖1說明了調度程序的代理,監(jiān)事和狀態(tài)存儲之間的關系。
圖1 - 在調度程序代理管理者模式的演員
注意:
此圖顯示的模式的簡化圖。在實際的實現(xiàn)中,有可能是調度程序的多個實例同時運行的任務的每個子集。類似地,系統(tǒng)可以運行每個代理程序的多個實例,或者甚至多個監(jiān)控器。在這種情況下,主管必須協(xié)調其與對方認真的工作,以確保它們不會爭來恢復同樣失敗的步驟和任務。在領導人選舉模式提供一個可能的解決了這個問題。
何時一個應用程序希望執(zhí)行一個任務,它提交一個請求給調度程序。調度記錄有關的任務及其步驟(例如,“步驟還未開始”)中的狀態(tài)存儲的初始狀態(tài)的信息,然后開始執(zhí)行由流程定義的操作。作為調度程序開始每一步時,它將更新關于該步驟中的狀態(tài)存儲(例如,“步運行的”)的狀態(tài)的信息。
如果一個步驟引用遠程服務或資源時,調度程序將消息發(fā)送給適當代理。該消息可以包含代理需要傳遞給服務或訪問該資源,除了完整的通過時間的操作的信息。如果代理成功完成其操作時,它返回到調度程序的響應。然后調度程序可以更新在狀態(tài)存儲的狀態(tài)信息(例如,“步驟完成”),并進行下一步驟。這個過程繼續(xù),直到整個任務完成。
代理可以實現(xiàn)任意重試邏輯需要執(zhí)行它的工作。但是,如果該代理之前,完成未完成其工作期間屆滿的調度程序就會認為操作失敗。在這種情況下,代理應該停止其工作,并沒有試圖東西返回到調度程序(甚至沒有錯誤消息),或者進行任何形式的恢復。這樣做的原因的限制是,后一步驟中已超時或失敗,則代理的另一個實例可被調度來運行失敗的步驟(該過程將在后面描述)。
如果代理本身出現(xiàn)故障時,調度程序將不會收到回復。該模式可能不會讓這一步驟已超時,一個已經(jīng)失敗的真正區(qū)別。
如果一個步驟超時或失敗時,狀態(tài)存儲將包含一個記錄,指出該步驟是否正在運行(“步驟運行”),但完全通過時間已經(jīng)過去了。監(jiān)事查找步驟,如本,并試圖恢復它們。一個可能的策略是為超級更新完成由值來擴展可用來完成步驟的時間,然后將消息發(fā)送到調度器識別已超時的步驟。然后,調度程序可以嘗試重復此步驟。然而,這樣的設計要求為冪等的任務。
這可能是必需的管理者防止如果連續(xù)失敗或者超時被重試相同步驟。為了實現(xiàn)這一點,對管理可維持一個重試計數(shù)為每一步,隨著狀態(tài)信息,在該狀態(tài)存儲。如果該計數(shù)超過預定閾值的管理者可以采用一種策略,例如,通知它應重試步驟中,在期望的故障將在這段時間內(nèi)可以解決調度之前等待較長的時間?;蛘?,該管理者可以將消息發(fā)送到調度請求將整個任務通過實現(xiàn)補償交易被撤消(該方法將依賴于調度程序和代理提供所必需的信息,以實現(xiàn)對已成功完成各步驟的補償操作)。
注意:
這不是管理者的目的來監(jiān)控調度程序和代理商,如果他們不能重新啟動它們。系統(tǒng)的這方面應該由其中這些組件所運行的基礎設施進行處理。同樣,管理者不應該是由調度所執(zhí)行的任務正在運行(包括如何補償應這些任務失?。┑膶嶋H業(yè)務運作的知識。這是由調度程序執(zhí)行的工作流邏輯的目的。監(jiān)事的責任是確定的步驟是否已失敗,并安排要么為它重復或者包含失敗的步驟,整個任務被取消。
如果該調度程序是失敗的,或者工作流程后,重新啟動正在由調度程序進行意外終止,該調度程序應能確定任何飛行任務,這是處理失敗時的狀態(tài),并準備繼續(xù)這個任務從該點上失敗了。該方法的實現(xiàn)細節(jié)都可能是特定的系統(tǒng)。如果任務不能恢復,這可能是必要的,以撤消該任務已經(jīng)完成的工作。這可能還需要執(zhí)行一個補償事務。
這種模式的主要優(yōu)點是,該系統(tǒng)是彈性的意想不到的臨時或不可恢復故障的情況下。該系統(tǒng)可以構造成可自愈。例如,如果一個代理程序或調度程序崩潰時,一個新的可啟動的,因而管理可以安排要恢復的任務。如果管理者發(fā)生故障,另一實例可以啟動,并且可以從發(fā)生故障的接管。如果管理者計劃定期運行,一個新的實例可以被自動預定義的時間間隔后啟動。該狀態(tài)存儲可以被復制以實現(xiàn)更大程度的彈性。
在決定如何實現(xiàn)這個模式時,您應考慮以下幾點:
使用這種模式時,在分布式環(huán)境中運行,例如云的方法必須是有彈性的,以通信故障和/或運行故障。
這種模式可能不適合任務不調用遠程服務或訪問遠程資源。
實現(xiàn)一個電子商務系統(tǒng)中的 Web 應用程序已經(jīng)部署在微軟的 Azure。用戶可以運行此應用程序來瀏覽提供一個組織的產(chǎn)品,下訂單,這些產(chǎn)品。用戶接口運行作為一個網(wǎng)絡的作用,并且該應用程序的命令處理元件被實現(xiàn)為一組工作角色。訂單處理邏輯的一部分包括訪問遠程服務,該系統(tǒng)的這一方面可能是易發(fā)生的瞬態(tài)或更持久的故障。為此,設計師使用了調度程序代理管理者模式實現(xiàn)了系統(tǒng)的訂單處理單元。
當客戶下訂單時,應用程序構建了一個消息,說明的順序和該職位的消息到隊列中。一個單獨的提交過程中,工人的角色運行,檢索此消息,將訂單到訂單數(shù)據(jù)庫的詳細信息,并為在國家商店的訂單流程的記錄。請注意,插入到常規(guī)數(shù)據(jù)庫和國家存儲作為同一操作的一部分執(zhí)行。提交過程的設計,以確保兩個刀片共同完成。
該提交進程創(chuàng)建的訂單包括狀態(tài)信息:
在這種狀態(tài)信息,OrderID 字段從新訂單的訂單 ID 復制。該 LockedBy 和 CompleteBy 字段設置為 null,則 ProcessState 字段設置為待定,并且 FailureCount 字段設置為 0。
注意:
在這個例子中,為了處理邏輯比較簡單,只包括一個調用的遠程服務的單個步驟。在一個更復雜的多步驟的情況下,提交過程很可能涉及多個步驟,所以多個記錄將在狀態(tài)存儲,每一個描述了一個單獨的步驟中的狀態(tài)被創(chuàng)建。
該調度程序同時作為一個輔助角色的一部分,實現(xiàn)了處理訂單的業(yè)務邏輯。調度輪詢新訂單的一個實例探討了狀態(tài)存儲的記錄,其中 LockedBy 字段為空,并在 ProcessState 場待定。何時調度程序發(fā)現(xiàn)一個新的訂單,立刻填充LockedBy 字段與它自己的實例 ID,設置 CompleteBy 字段到一個適當?shù)臅r間,并設置 ProcessState 字段來處理。執(zhí)行此代碼的設計是獨特和原子,以確保調度程序的兩個并發(fā)實例不能試圖同時處理的順序相同。
調度程序將運行業(yè)務流程處理訂單異步,從狀態(tài)存儲傳遞給它的值在 OrderID 字段。工作流處理的順序檢索來自數(shù)據(jù)庫的訂單訂單的詳細信息,并執(zhí)行其工作。當訂單處理流程的步驟需要調用遠程服務,它使用一個代理。在工作流步驟的代理通過利用對作為請求/響應信道 Azure 的服務總線消息隊列進行通信。圖2示出了該解決方案的一個高層視圖。
圖2 - 使用調度程序代理管理者模式在 Azure 的解決方案來處理訂單
從一個工作流步驟發(fā)送到代理的消息描述的順序,并包括 CompleteBy 時間。如果代理接收來自遠程服務的響應的 CompleteBy 時間到期之前,構建其上的服務總線隊列在其上的工作流是聽張貼答復消息。當工作流步驟接收到有效的應答消息,它完成它的處理和調度臺的訂單狀態(tài) ProcessState 場處理。在這一點上,為了處理已成功完成。
如果 CompleteBy 時間到期的代理接收來自遠程服務的響應之前,代理簡單地停止其處理,并終止處理順序。類似地,如果工作流處理的順序超過了 CompleteBy 時,它也將終止。在這兩種情況下,在該狀態(tài)存儲在順序的狀態(tài)保持給定處理中,但 CompleteBy 時間指示的時間用于處理訂單已經(jīng)過去,該處理判定為不合格。請注意,如果正在訪問遠程服務,或者正在處理的順序工作流(或兩者)的代理意外終止,在狀態(tài)存儲的信息將再次保持設置為處理,最終將有過期 CompleteBy 值。
如果代理檢測到不可恢復的非瞬時性故障當它正在嘗試聯(lián)系遠程服務,它可以發(fā)送一個錯誤響應返回到工作流。該調度程序可以設置為錯誤,并提出了警示操作者的事件的狀態(tài)。然后,操作者可以嘗試手動解決失敗的原因,并重新提交失敗的處理步驟。
主管定期檢查狀態(tài)存儲在尋找訂單,過期 CompleteBy 值。如果管理者發(fā)現(xiàn)這樣的記錄,它增加了 FailureCount 領域。如果 FailureCount 值低于規(guī)定的閾值時,所述管理者復位 LockedBy 字段為空,更新 CompleteBy 場與新的到期時間,并設置 ProcessState 字段待定。調度程序的一個實例可以拿起這個命令并執(zhí)行其處理如前。如果 FailureCount 值超過特定閾值時,對故障的原因被假定為非瞬態(tài)。監(jiān)事設置為錯誤的狀態(tài),并引發(fā)了警報操作,如前所述的事件。
注意:在這個例子中,管理者是在一個單獨的工作任務落實。您可以使用各種策略來安排監(jiān)理任務運行,包括使用 Azure 的計劃程序服務(不要與計劃程序組件在此模式相混淆)。關于Azure的計劃程序服務的更多信息,請訪問調度程序頁面。
雖然未在本實施例中所示,該調度程序可能需要保留在通知關于單的進度及狀態(tài)首位提交的順序應用。應用程序和調度程序彼此分離,以消除它們之間的任何相關性。該應用程序并不知道哪個調度的實例處理的順序,調度不知道它的具體應用實例發(fā)布的順序。
為使訂單狀態(tài)予以報道,該應用程序可以使用自己的私人響應隊列。這個響應隊列的詳細信息將被納入送往提交過程的要求,其中包括在狀態(tài)存儲這些信息的一部分。該調度程序隨后將郵件投遞到該隊列表示訂單的狀態(tài)(“接收到的請求”,“為了完成”,“訂單失敗”,等等)。它應包括訂單ID在這些消息中,以便它們可以與由該應用程序的原始請求相關聯(lián)。
更多建議: