本文章是由機器翻譯。

工作流服務

使用 Windows Server AppFabric 創建長時間運行的可伸縮工作流

Rafael Godinho

下載代碼示例

業務流程可能會涉及各種各樣的應用場景。它們可以包括人工流程、通過服務公開的業務邏輯、展示層的協調甚至應用程式集成。

儘管這些場景各不相同,成功的業務流程還是有一些共同之處的。它們必須很容易構建、使用和修改。它們必須可伸縮,能夠滿足不斷變化的業務需求。並且,它們通常還需要進行某種形式的狀態記錄、合規性和調試。

工作流就是一個編寫成應用程式的業務流程的很好例子。它們包含了我提到的所有這些元素:人的業務需求、業務邏輯、人與應用程式之間的協調以及輕鬆輸入資料和檢索狀態的功能。應用程式有很多工作要做,因此需要編寫很多代碼。

幸運的是,Microsoft .NET Framework 和 Windows Server AppFabric 提供了全套工具,可説明您創建、部署和配置長時間運行的、可跟蹤的工作流服務。您可能已經很熟悉 .NET Framework。Windows Server AppFabric 是一組 Windows Server 擴展,其中包括針對基於 Windows Communication Foundation (WCF) 和 Windows Workflow Foundation (WF) 的服務的緩存和託管服務。

本文將向您介紹使用 WCF、WF 和 Windows Server AppFabric 構建簡單可伸縮工作流服務的過程。

創建工作流服務

若要創建工作流服務,您需要綜合使用兩項技術:WCF 和 WF。這種集成對開發人員來說是無縫的,其實現方式是通過使用特定的消息傳送活動在工作流中接收 WCF 消息。工作流託管在各個工作流的 WCF ServiceHost (WorkflowServiceHost) 中,為這些消息提供了 WCF 端點。在消息傳送活動組中,有兩種活動可用來接收資訊,從而使工作流能夠在發生 Web 服務調用時從外部用戶端接收消息:Receive 活動和 ReceiveAndSendReply 範本。

Receive 活動用於接收要由工作流處理的資訊。它幾乎可以接收所有類型的資料,例如內置資料類型、應用程式定義的類,甚至是 XML 序列化的類型。图 1 在工作流設計器中顯示了一個 Receive 活動的示例。

圖 1 工作流設計器上的 Receive 活動

這種活動具有大量屬性,但其中四個屬性尤為重要,應該加以注意:

  • CanCreateInstance 用於確定工作流運行時是必須創建新的工作流實例來處理傳入的消息,還是可以通過關聯技術重複利用現有的工作流實例。稍後我將更詳細地討論關聯。您可能希望在工作流的第一個 Receive 活動上,將其設置為 True。
  • OperationName 指定由此 Receive 活動實現的服務操作名稱。
  • Content 指示要由服務接收的資料。這與 WCF 服務操作合約參數極其相似。
  • ServiceContractName 用於在所生成的 Web 服務描述語言 (WSDL) 內創建服務合約分組服務操作。

如果單獨使用 Receive 活動,則它將實現單向消息交換模式,用於從用戶端接收資訊,而不向用戶端發送回復。通過將 Receive 活動與 SendReply 活動相關聯,這種活動也用於實現請求-回應模式。

為了説明實現請求-回應模式,WF 向 Visual Studio 工具箱中添加了一個名為 ReceiveAndSendReply 的選項。將此選項放到工作流設計器上時,它會自動在 Sequence 活動內創建一對預先配置好的 Receive 和 SendReplyToReceive 活動(請參見圖 2)。

圖 2 工作流設計器上的 ReceiveAndSendReply

ReceiveAndSendReply 範本背後的原理是在 Receive 和 SendReplyToReceive 操作之間執行一些處理操作。但是,特別要注意的是,在 Receive 和 SendReplyToReceive 對之間不允許持久性。它將創建一個非持久的區域,該區域僅持續到兩項活動均結束時。這意味著如果工作流實例變為空閒,即使主機被配置為在工作流空閒時仍然保留工作流,該工作流仍然不會保留。如果某項活動嘗試在非持久區域中顯式保留工作流實例,將引發致命異常,工作流將中止,並且會向調用者返回異常。

關聯調用

有時,業務流程可能會收到多個外部調用。在出現這種情況時,會在第一次調用時創建一個新的工作流實例,接著執行該工作流的活動,然後該工作流就會進入空閒狀態,等待後續的調用。當後續調用達到時,該工作流實例將結束空閒狀態,並繼續執行。

通過這種方式,工作流運行時必須有一種方法,能夠使用其在後續調用中收到的資訊,並且能夠將此資訊與以前創建的工作流實例相區別,從而繼續處理。否則,它可能會調用任意實例,從而使整個流程的一致性面臨風險。這稱為關聯,您可以將後續調用關聯到與該調用相關的待定工作流。

關聯表現為一種 XPath 查詢,它可以識別特定消息中的特定資料。可以使用 InitializeCorrelation 活動或通過向類似下列活動的 CorrelationInitializers 屬性指定值,對關聯進行初始化:Receive、SendReply、Send 和 ReceiveReply。

此初始化過程可以在代碼中完成,也可以從 Visual Studio 2010 中使用工作流設計器來完成。因為 Visual Studio 提供了一個嚮導,可説明創建 XPath 查詢,所以這種方法對大多數開發人員來說都更簡單,也更願意採用。

可能需要使用關聯的一種情況就是開支報告工作流。首先,某位員工提交開支報告資料。隨後,其經理可以審核該報告,並且批准或拒絕該支出(請參見圖 3)。

圖 3 開支報告示例場景

在此場景中,在工作流向員工的用戶端應用程式返回回應時,就會創建關聯。若要創建關聯,您需要一些能夠標識上下文的資訊,例如開支報告 ID(可能已經是唯一 ID)。然後,工作流示例變為空閒,等待經理批准或拒絕開支報告。當經理的用戶端應用程式發出批准調用時,工作流運行時會將收到的開支報告 ID 與以前創建的工作流實例相關聯,從而繼續流程。

若要在 Visual Studio 2010 中創建關聯,請先在工作流設計器中選擇要用來初始化關聯的活動。在我的示例中,這是向用戶端返回開支報告 ID 的活動。在 SendReply 活動中,我通過按一下省略號按鈕,在“屬性”視窗中設置了 CorrelationInitializers 屬性。這將顯示“添加相關初始值設定項”對話方塊(請參見圖 4),您可以在此配置關聯。

圖 4 設置 XPath 查詢關聯

有三項必須設置:關聯控制碼、關聯類型和 XPath 查詢。關聯控制碼是工作流運行時用來存儲關聯資料的變數,由 Visual Studio 自動創建。

下一步是設置關聯類型。.NET Framework 提供多種類型的關聯,但因為我需要查詢與用戶端交換的部分資訊,即基於內容的關聯,所以我的最佳選擇是使用 Query 關聯初始值設定項。完成此操作後,可以將 XPath 查詢設置為開支報告 ID。當我按一下箭頭時,Visual Studio 會檢查消息內容,並顯示一個清單,用於選擇適當的資訊。

若要在開支批准後繼續執行工作流,相應的 Receive 活動必須使用此關聯。通過設置 CorrelatesOn 屬性可以實現這一點。請在“屬性”視窗中按一下屬性附近的省略號按鈕,以便打開“CorrelatesOn 定義”對話方塊(請參見圖 5)。在此對話方塊中,需要將 CorrelatesWith 屬性設置為用來為 SendReplyToReceive 活動初始化關聯的相同控制碼,並且必須將 XPath 查詢屬性設置為通過開支報告批准消息收到的相同鍵值和開支報告 ID。

圖 5 CorrelatesOn 定義

WF 附帶了一組通用活動,名為基本活動程式庫 (BAL)。我將使用其中部分活動來發送和接收資訊。儘管它們非常實用,但有時還是需要使用與業務規則關聯更緊密的活動。基於我到目前為止討論的場景,需要使用三種活動來提交和批准開支報告:Create、Approve 和 Deny 開支報告。由於這些活動都非常相似,我將只展示 CreateExpenseReportActivity 的代碼:

public sealed class CreateExpenseReportActivity 
  : CodeActivity<int> {
  public InArgument<decimal> Amount { get; set; }
  public InArgument<string> Description { get; set; }
  protected override int Execute(CodeActivityContext context) {
    Data.ExpenseReportManager expenseReportManager = 
      new Data.ExpenseReportManager();
    return expenseReportManager.CreateExpenseReport(
      Amount.Get(context), Description.Get(context));
  }
}

該活動接收開支的金額和描述,這兩種資訊均聲明為 InArgument。大部分繁重的工作都在 Execute 方法中完成。它訪問一個類,該類使用實體框架來處理資料庫訪問以及保存開支報告資訊,而實體框架在另一端返回開支報告 ID。我只需要執行 CLR 代碼,而不需要與 WF 運行時交互,因此最簡單的選擇是創建繼承自 CodeActivity 的活動。完整的工作流如圖 6 所示。

圖 6 完整的開支報告工作流

託管工作流服務

創建工作流服務之後,您需要決定它在何處運行。傳統的選擇是在您自己的託管環境中運行,例如 IIS 或 Windows Process Activation Services (WAS)。但另一種選擇是充分利用 Windows Server AppFabric。Windows Server AppFabric 針對託管、管理、保護和伸縮通過 WCF 或 WF 創建的服務,增強了 Windows Server 2008 R2 中的“應用程式伺服器”角色。您也可以在運行 Windows Vista 或 Windows 7 的 PC 上使用 Windows Server AppFabric,進行開發和測試。

儘管 IIS 和 WAS 已經支援服務託管,Windows Server AppFabric 還是提供了一種更實用、更容易管理的環境,該環境集成了 WCF 和 WF 功能,例如持久性以及通過 IIS 管理器進行跟蹤。

簡化的工作流持久性

在處理您的所有業務流程時,電腦擁有的資源仍然是有限的,因此沒有理由將計算資源浪費在空閒工作流上。對於長期運行的流程,您可能無法控制從流程開始到流程結束所需的總時間。它可能需要幾分鐘、幾小時、幾天,甚至更長。如果它依賴于外部實體,例如其他系統或最終使用者,則它大部分時間都處於空閒狀態,僅僅用來等待回應。

WF 提供了一種持久性框架,能夠將工作流實例狀態的持久快照(與流程或電腦資訊無關)存儲到實例存儲中。WF 4 本身已經附帶一個 SQL Server 實例存儲。但是,因為 WF 很容易擴展,我可以自行創建實例存儲,以便根據需要保留工作流實例的狀態。當工作流實例變為空閒狀態並被保留之後,它可以卸載到預留記憶體和 CPU 資源,最終在伺服器場之間的各個節點之間來回移動。

Windows Server AppFabric 有一種簡便方法,可以設置和維護與 WF 持久性功能的集成。整個流程對工作流運行時是透明的,而工作流運行時會將持久性任務委託給 AppFabric,從而擴展了預設的 WF 持久性框架。

配置持久性的第一步是使用 Windows Server AppFabric 配置嚮導或 Windows PowerShell cmdlet 來設置 SQL Server 資料庫。如果持久性資料庫不存在,該嚮導可以創建該資料庫;也可以僅僅創建 AppFabric 架構。在創建資料庫之後,其他所有步驟都在 IIS 管理器中完成。

在 IIS 管理器中,按右鍵要配置的節點(伺服器、網站或應用程式)並選擇“管理 WCF 和 WF 服務”|“配置”以打開“為應用程式配置 WCF 和 WF”對話方塊,然後按一下“工作流暫留”(請參見圖 7)。您會看到,您可以選擇啟用或禁用工作流持久性。

圖 7 配置工作流持久性

您還可以設置當工作流變為空閒時,工作流運行時將花多長時間將工作流實例從記憶體中卸載並將其保留到資料庫中。預設值為 60 秒。如果您將該值設為 0,則將立即保留工作流實例。這對於通過負載平衡器進行擴展來說尤其重要。

工作流跟蹤

有時,與外部使用者或應用程式交互的進程可能會出錯。由於長期運行的進程具有獨立的特性,在這些場景中情況甚至更糟。在出現問題時,開發人員通常需要分析一批日誌,以便找出發生了什麼問題、如何再現該問題,以及最重要的,如何更正該問題並使系統保持正常運行。如果您使用的是 WF,這種框架中已經內置了這種日誌功能。

同樣,WF 具有一個可擴展的框架用於保留空閒實例,它還具有一個可擴展的框架用於顯示工作流的執行情況。此框架稱為跟蹤。在此框架執行期間,它將透明地通知工作流記錄關鍵事件。Windows Server AppFabric 使用此擴展能力來提高內置的 WF 跟蹤功能,在 SQL Server 資料庫中記錄執行過程中的事件。

Windows Server AppFabric 的跟蹤配置與用於持久性的跟蹤配置類似,可以通過 Windows Server AppFabric 配置嚮導或 Windows PowerShell cmdlet 進行訪問。在前文討論的“為應用程式配置 WCF 和 WF”對話方塊中,按一下“監視”。現在,您可以選擇啟用或禁用跟蹤,還可以選擇跟蹤級別,如圖 8 所示。

圖 8 在 Windows Server AppFabric 上啟用跟蹤

在 Windows Server AppFabric 中配置跟蹤時,您可以選擇五種監視級別:

  • “關”與禁用監視具有同樣的效果,最適合用在希望盡可能降低跟蹤開銷的場景。
  • “僅錯誤”僅顯示嚴重事件,例如錯誤和警告。此模式最適合僅需要進行最低限度的錯誤記錄的高性能場景。
  • “運行狀況監視”是預設的監視級別,它包含“僅錯誤”級別記錄的所有資料,加上一些額外的處理資料。
  • “端對端監控”包含“運行狀況監視”級別記錄的所有資料,加上用於重構整個消息流的額外資訊。此級別用在一個服務調用另一個服務的場景。
  • “故障排除”正如其名,是最詳細的級別,對應用程式不能正常運行且需要修復的場景非常有用。

擴展工作流服務

由於 Windows Server AppFabric 擴展了 Windows Server 中的應用程式伺服器角色,它從其前身繼承了高度可擴展的基礎結構,可運行于網路負載平衡器 (NLB) 之後的伺服器場中。您也可以看到它能夠根據需要保留和跟蹤工作流實例。因此,若要託管長期運行的工作流程並支援從用戶端發出的大量請求,Windows Server AppFabric 是一種極佳的選擇。

工作流服務可擴展環境的示例可參見圖 9。它具有兩個 Windows Server AppFabric 實例,兩者都運行相同的工作流定義的副本。NLB 將請求路由到可用的 AppFabric 實例。

圖 9 可擴展環境中的工作流

在開支報告場景中,當用戶端首次訪問該服務以創建一份開支報告時,平衡器會將請求重定向至一個可用的 Windows Server AppFabric 實例,該實例將開支資料保存到資料庫中,將生成的 ID 返回給用戶端,並且由於工作流變為空閒狀態,等待工作流運行時批准該開支,因而將正在運行的實例保留到資料庫中。

隨後,當用戶端應用程式訪問該服務以批准或拒絕開支報告時,NLB 會將請求重定向至一個可用的 Windows Server AppFabric 實例(可與第一次服務調用時的伺服器不同),並且伺服器將關聯該請求,並從持久性資料庫中恢復該工作流實例。現在,記憶體中的實例將繼續進行處理,將批准保存到資料庫中,然後在完成後返回用戶端。

結束語

正如您看到的,在負載平衡環境中,將工作流服務與關聯、持久性和跟蹤相結合,是在可擴展環境中運行這些服務的一種強大的技術。組合使用這些功能可提高操作效率,允許對正在運行的服務執行主動的操作,以及線上程、進程甚至電腦之間分配工作流。通過這種方式,開發人員就可以創建可全面擴展的解決方案,該方案可在一台電腦上運行,也可以在大型的伺服器場中運行,而無需擔心基礎結構的複雜性。

有關利用 WCF 和 WF 設計工作流的詳細資訊,請務必閱讀 Leon Welicki 的文章“使用 WCF 和 WF 4 的工作流視覺化設計”,該文章發表在 MSDN 雜誌 的 2010 年 5 月號上 (msdn.microsoft.com/magazine/ff646977)。有關長期運行的進程和工作流持久性的更深入討論,請參見 Michael Kennedy 的文章“支援長時間運行操作的 Web 應用程式”,該文章發表在 2009 年 1 月號上 (msdn.microsoft.com/magazine/dd296718)。

有關 Windows Server AppFabric 的詳細資訊,請參見 Windows Server 開發人員中心,網址為 msdn.microsoft.com/windowsserver/ee695849

Rafael Godinho 是 Microsoft Brazil 的 ISV 開發推廣人員,他負責説明本地合作夥伴應用 Microsoft 技術。 您可以通過 Godinho 的博客 blogs.msdn.com/rafaelgodinho 與他聯繫。

衷心感謝以下技術專家對本文的審閱:Dave CliffeRon JacobsLeon Welicki