使用 Windows Server AppFabric 管理工作流服务






4.96/5 (11投票s)
介绍 Windows Server AppFabric。
在您开始之前
虽然不是必需的,但建议您先阅读我关于工作流 4 持久化和跟踪的文章(WF4Extensions.aspx)。这将使您能够比较自托管(在上一篇文章中讨论)和 AppFabric 托管(在本文中讨论)。
此外,为了充分利用本文的价值,您需要下载并设置附加的项目到您的机器上(需要 VS2010)。本文的内容依赖于您已成功运行了这些项目。
假设
假定您已具备 Windows Workflow Foundation 和 Windows Communication Foundation 的基本知识。同时,还需要熟悉 IIS 7 和 WAS。
您还应该能够熟练地使用 Visual Studio 并设置项目和解决方案。
AppFabric 的安装和配置是一个简单的向导过程,此处不进行介绍。本文的重点是展示 AppFabric 的实际应用,并通过实际示例来深入了解其各个部分。
本文讨论的所有示例都需要 VS2010 和 Windows Server AppFabric。
引言
如果您曾经进行过复合 Web 应用程序开发,那么您肯定熟悉与之相关的问题。考虑以下场景:您想构建一个 ASP.NET 应用程序,调用使用 WF 服务构建的业务流程(一个发布为 WCF 服务的 WF 业务流程)。现在,让我们看看您在使用 WF 服务时通常会面临的挑战和需求:
- 托管:在 WCF 中,您有多种托管选项。构建一个健壮且可靠的宿主确实是一项艰巨的任务,因此您通常会依赖 IIS 和 WAS。然而,虽然 WAS 为您的服务提供了增强的托管体验,但您仍然希望获得比 WAS 所能提供的更多控制权。
- 管理:通过配置文件管理您的服务是很常见的,但容易出错。在 IIS 和 WAS 之上拥有一个 UI 来管理服务是一个非常有吸引力的需求。
- 监控:您的 WF 服务是一个业务流程,您绝对希望能够介入并监控特定实例的进度和业务流程。
- 跟踪:在业务流程的各个阶段跟踪实例变量可以帮助您深入了解正在进行的进度。
- 持久化:在设计长期运行的进程时,持久化变得非常普遍。在业务流程的某些阶段,您希望将状态持久化(序列化并存储到介质中),例如 SQL Server。这样,您可以卸载该进程——例如,它正在等待输入——然后从同一介质中重新加载它。
- 扩展:持久化提供了扩展您进程的能力。在机器 A 上运行的实例可以持久化到 SQL Server,稍后可以重新加载到机器 B 上,并从最后一个持久化点继续执行。
- 缓存:Web 应用程序中的缓存存在一个常见问题:可伸缩性。缓存是单个机器的内存属性。因此,如果负载均衡器将用户请求从机器 A 转发到机器 B,机器 A 中的任何内存数据在机器 B 中都会丢失。到目前为止,解决此可伸缩性问题只能通过第三方解决方案来实现。
Windows Server AppFabric 提供了一组 Windows Server 扩展,它们充当构建复合 Web 应用程序的基础结构。更实际地说,这些扩展有助于应对上述所有需求。
本文的其余部分将展示 AppFabric 的实际应用,并通过演示来处理和详细阐述这些需求。
演示第一个示例:Hello WF Service
第一个示例(附加在 HelloWFService.zip 中)包含三个项目:
- HelloService:一个简单的 WCF 服务,公开一个操作,该操作接受字符串参数并返回字符串值。
- HelloWFService:这是包含业务流程的工作流服务。它使用 WCF Workflow Service Application 项目模板构建。
- TestClient:一个调用工作流服务的控制台应用程序。
让我们检查 HelloWFService 项目中的业务流程。
TestClient 控制台应用程序调用服务操作 SubmitOrder,并传递一个字符串参数。SubmitOrder 向控制台应用程序返回一条消息,然后其任务就结束了。工作流服务然后继续执行并调用活动 ProcessOrder,该活动调用 WCF 服务(HelloService),并传递控制台应用程序提交的相同参数。
当您向 WCF 服务添加服务引用并生成项目时,ProcessOrder 活动会自动在 VS 工具箱中创建。
AppFabric 初探
当您将上述解决方案部署到您的机器上时,您将在 IIS 中托管两个 WCF 服务:HelloService WCF 服务和 HelloWFService WCF 工作流服务。
打开 IIS 管理器(或者,如果安装了 AppFabric,则可以转到“所有程序”->“Windows Server AppFabric”->“IIS 管理器”)。您会看到一个新的 AppFabric 选项卡,如下所示:
该选项卡包含三个图标:
- AppFabric Dashboard:用于监控所有服务活动的地方……您将非常熟悉这个地方。
- Endpoints:用于配置服务中公开的 WCF 端点的地方。
- Services:用于配置 WCF 项目的服务文件的地方。
如果您单击“默认网站”,如上图所示,AppFabric 选项卡中显示的数据将对应于默认网站下托管的所有服务。然而,如果您单击单个服务,则数据仅对应于该特定服务。
现在,让我们开始配置服务。右键单击 HelloWFService 并选择“管理 WCF 和 WF 服务”->“配置”。
选择“监控”选项卡。在这里,您可以指定服务所需的监控级别以及存储监控事件的源。在下面的图像中,我选择了在 AppFabric 配置向导中创建的数据库,并选择了“健康监控”级别,这对于我在此示例中想要的监控级别来说足够了。在此步骤中要小心,因为监控级别越高,应用程序的开销就越大。在开发和测试阶段选择“故障排除”级别。对于生产环境,“健康监控”甚至“仅错误”就足够了。
在“工作流持久化”选项卡中,选择“自定义”或“无”。我们将在稍后讨论持久化。
为了本次讨论,无需进一步配置;随着我们继续进行,将涵盖一些其他配置选项。
现在让我们运行示例:生成解决方案并启动控制台应用程序“TestClient”,然后等待直到您看到消息“Your order is under process”。让我们快速回顾一下刚才发生的事情:控制台应用程序调用了工作流服务并收到了消息;在幕后——这是控制台应用程序客户端看不到的——工作流服务一定调用了 WCF 服务。
打开 AppFabric Dashboard 并检查统计信息。
因此,总共有两次 WCF 调用和一次 WF 服务调用。两次 WCF 调用实际上一次是针对 HelloService WCF 服务,一次是针对 HelloWFService 工作流服务。WF 服务调用是 HelloWFService(WF 实例历史记录是 WCF 调用历史记录的子集)。
AppFabric 已为我们跟踪了服务调用活动。您还可以查看是否有任何错误,以及已完成的服务调用与未完成的服务调用。您还可以钻取更多详细信息;右键单击 Dashboard 中的 WF 服务,然后选择“Tracked WF Instances”,如下所示:
在结果屏幕中,您将看到有关 WF 实例的更多详细信息,如下所示:
到目前为止,您所看到的是出色的报告,但请记住,我们还配置了我们的服务进行监控(使用健康监控级别)。要查看此情况,请右键单击“Service1”并选择“View Tracked Events”(您也可以从第一个 Dashboard 页面访问监控)。您现在将看到以下屏幕:
正如您所见,在这里,您可以通过检查形状的名称和执行顺序来监控业务流程的流。
持久化
持久化是构建长期运行业务流程时一个非常重要的概念。在您的服务的特定点,您希望持久化(序列化并存储到介质中——通常是数据库)实例状态,以便在发生故障时,您可以从最后一个持久化点恢复该实例。
在此示例中,我们将看到持久化的实际应用。此概念的另一种变体是“卸载”。虽然持久化“本身”意味着持久化但保持实例在内存中,但卸载意味着持久化并从内存中移除实例。这当然为扩展您的服务提供了可能性,因为一个实例可以从一台机器上刷新到内存中,而稍后又可以在另一台机器上继续执行。卸载将在稍后的示例中介绍。
因此,为了看到持久化的实际应用,请返回 Visual Studio 并打开“Service1.xamlx”,然后进行此更改:选中“SendResponse”形状的“PersistBeforeSend
”属性。这仅仅意味着在向控制台应用程序发送响应之前,实例状态将被持久化;然而,如前所述,实例本身将继续执行。
另一项更改在 IIS 中:选择 HelloService 应用程序,然后在“管理 WCF 和 WF 服务”部分中单击“停止应用程序”。
最后,我们需要为我们的 WF 服务配置持久化。在 IIS 中,右键单击“HelloWFService”,然后选择“管理 WCF 和 WF 服务”->“配置”。在“持久化”选项卡中,选择您通过 AppFabric 配置向导配置的默认持久化数据库,如下所示:
提示:当您处于开发/测试阶段时,您可能会发现 AppFabric 中堆积的统计信息会使您难以专注于某个特定场景。如果您需要(就像我在开发中总是做的那样),您可以清除 AppFabric 数据库以获得全新的开始。我博客上的这篇帖子(http://thedotnethub.blogspot.com/2010/05/clean-appfabric-databases.html)展示了如何操作。
一切就绪后,生成解决方案并再次运行控制台应用程序。
在这种情况下会发生什么?控制台客户端调用 WF 服务,该服务——在发送响应之前——持久化状态并继续执行。接下来,WF 服务尝试调用已停止的 WCF 服务,从而应该抛出错误。现在,让我们检查 AppFabric Dashboard 并看看发生了什么。
对 WCF 服务的失败调用记录在 WF 实例历史记录的“失败”部分,并设置为“未恢复”状态。另一个需要注意的重要事项是“持久化的 WF 实例”部分;WF 服务实例已持久化。右键单击挂起的实例并选择“持久化的 WF 实例”,如下所示:
接下来,您将看到持久化的 WF 实例处于“挂起”状态。关于这一点最棒的是,您可以右键单击该实例并选择“恢复”,如下所示:
然而,在那之前,请重启 WCF 应用程序。在 IIS 中,选择 HelloService 应用程序,然后单击“启动应用程序”。
现在恢复 WF 实例。等待几秒钟(直到 Windows 服务启动),然后刷新以查看实例已恢复执行并成功完成。由于最后一个持久化点(实际上是唯一的那个)就在将响应发送到控制台应用程序之前——之后在调用 WCF 服务时发生故障——该实例从那里恢复,并尝试重新调用 WCF 应用程序。由于我们刚刚重新启动了 WCF 应用程序,这次调用成功了,WF 实例也成功完成了。如果您注意到 WF 实例历史记录部分,您将看到该实例已从“未恢复”状态移至“已恢复”状态。
演示第二个示例:Hello WF Service
第二个示例(附加在 SaleService.zip 中)最初是作为 AppFabric Beta 2 示例的一部分提供的,但我为了本文的目的对其进行了一些修改。它包含三个项目:
- SaleService:使用 WCF Workflow Service Application 项目模板构建的包含业务流程的 WF 服务。
- TestClient:一个消耗 WF 服务的控制台客户端(用于显示目录信息——稍后将解释整个过程)。
- TestClient2:另一个消耗 WF 服务的控制台客户端(用于预订或取消目录订单)。
业务流程如下图所示(它太大了,无法一次性展开并查看,但您可以双击每个部分来展开它):
当客户端(TestClient 控制台应用程序)请求浏览一系列目录信息时,流程开始(此处没有数据库,信息仅硬编码在流程本身中)。之后,流程等待一分钟;在此期间,另一个客户端(TestClient2 控制台应用程序)必须回复以确认购买。如果在没有 TestClient2 调用的一分钟内过去,则业务流程终止。
正如我一开始所说,这里不介绍工作流开发,而是需要基本知识,所以我不会介绍业务流程形状的细节。但是,使用我刚才给出的描述,浏览流程并查看形状应该足以让您详细理解正在发生的事情。
卸载
生成并部署解决方案;您将在 IIS 中获得一个名为“SaleService”的应用程序,该名称是在 Visual Studio 项目属性的 Web 选项卡中配置的。
就像我们在第一个示例中所做的那样,为项目配置健康监控。至于持久化,我们将做一些新的事情。在第一个示例中,我们只是通过 AppFabric 配置了持久化存储,并使用了 WF 设计器(通过设置 PersistBeforeSend
属性)。在这里,我们将额外使用 AppFabric 为我们的 WF 实例设置卸载时间。首先,设置持久化存储,如下所示:
然后设置卸载时间,如下所示:
我们刚刚指示我们的工作流服务在空闲 20 秒后卸载自身。现在会发生以下情况:第一个控制台应用程序发出请求以浏览目录。WF 进程配置为等待一分钟,直到收到第二个控制台的第二个请求以确认请求。如果没有发出第二个请求,进程将自行终止——这就是我们将在本示例中执行的操作。
运行第一个控制台应用程序,您将看到产品列表,如下所示:
现在切换到 AppFabric Dashboard,您应该会看到您的请求已记录,并且该进程处于“进行中”状态。此外,等待 20 秒,您还将在 Dashboard 中看到持久化实例的记录。为什么?因为我们已将服务配置为在空闲 20 秒后卸载自身。如下所示:
如果单击 WF 实例,您会看到它处于空闲状态。
现在再等待 40 秒(以便一分钟过去),然后刷新 Dashboard;您将看到持久化实例已消失,WF 实例已完成执行并自行终止。
理解持久化与卸载
到目前为止,我们已经体验了一个演示持久化的例子,另一个演示卸载的例子。我已经从技术角度描述了两者之间的区别。但是,在应该使用持久化的业务场景和应该使用卸载的业务场景之间,又有什么不同呢?
考虑一个场景,其中一个 WF 业务流程接受客户的购买请求;该流程必须通过 WCF 调用检查客户银行信用,并实时回复客户。场景本身**不是**长期运行的,会在几秒钟内完成。但是,如果 WCF 银行服务中断了呢?这是您无法预测但仍然必须防范的情况。在这种情况下,在调用 WCF 银行服务之前持久化您的业务流程是有意义的;这样,如果您检测到银行服务已停止并且抛出了异常,您总会有一个持久化点可以返回,并从那里尝试重新发送消息到 WCF 银行服务……直到它再次启动。嗯,这类似于我们的第一个示例。
现在考虑第二个场景,其中一个 PO WF 业务流程接受客户请求以浏览产品目录。然而,客户可以花时间决定是否继续订购;例如,他们可以花一天时间来决定。在这种情况下,您不想将 WF 进程保留在内存中;相反,您希望卸载它,并在客户发送他们的决定时再次唤醒它。嗯,这正是第二个示例中显示的场景。
总之,当您想确保安全并拥有一个在发生故障时可以返回的点时,您会使用持久化。另一方面,当您想释放资源并将您的进程从内存中移除时,尤其是在长期运行的进程中,您会使用卸载。最后,请仔细设计您的持久化(和卸载),因为序列化和将实例状态存储在数据库中会带来性能损失。
跟踪
跟踪是能够进入正在运行的工作流服务实例并查看实例生命周期中变量值的功能。
在从 AppFabric 配置跟踪之前,有一些概念是您需要了解的。简而言之,当您处理 WF 4.0 跟踪时,您必须了解三个概念:
- 跟踪记录:这些是由工作流发出的信息记录。有四种派生类对应四种类型的跟踪记录:
WorkflowInstanceQuery
:有关工作流实例状态的事件。例如:已启动、已挂起、已卸载等……ActivityStateQuery
:有关工作流内部活动的事件。CustomTrackingQuery
:任何您想跟踪的自定义信息。BookmarkResumptionQuery
:当此书签被恢复时您想跟踪的书签名称(书签在我在开头提到的 WF 文章中讨论)。- 跟踪配置文件:充当跟踪记录的过滤器,以便只跟踪所需信息。
- 跟踪参与者:跟踪信息将被写入的介质。WF 4.0 提供了一个写入 ETW(Windows 事件跟踪)的参与者。可以轻松开发自定义参与者,例如将跟踪数据写入 SQL Server。
在 IIS 中,单击“SaleService”应用程序,然后从 AppFabric 部分双击“Services”图标。右键单击服务名称并选择“Configure”,如下所示:
在结果屏幕中,选择“Monitoring”,然后单击“Configure”,如下所示:
从下拉列表“Tracking profile”中,选择“Sale Service Order Tracking”,如上所示。
现在,让我们切换到解决方案并将所有这些内容联系起来。打开 SaleService 项目的 web.config 文件,找到“Tracking”部分。此部分定义了一个名为“Sale Service Order Tracking”的跟踪配置文件;这与我们在 AppFabric 中刚刚配置的名称相同。
跟踪配置文件定义了我们要观察的跟踪记录。例如,跟踪配置文件声明我们想跟踪工作流实例的所有状态。相应的节是:
<workflowinstancequeries />
<workflowinstancequery />
<states />
<state name="*" />
</states />
</workflowinstancequery />
</workflowinstancequeries />
它还声明,当名为“Assign Catalog Expired Status”的活动(即工作流形状)进入“Closed”状态时,我们想跟踪变量“StatusText
”。相应的节是:
<activitystatequery activityname="Assign Catalog Expired Status" />
<states />
<state name="Closed" />
</states />
<variables />
<variable name="StatusText" />
</variables />
</activitystatequery />
同样,当名为“Process New Order”的活动进入“Closed”状态时,将跟踪变量“StatusText
”、“NewPurchaseOrder
”、“PurchaseTotal
”和“OrderId
”。相应的节是:
<activitystatequery activityname="Process New Order" />
<states />
<state name="Closed" />
</states />
<variables />
<variable name="StatusText" />
<variable name="NewPurchaseOrder" />
<variable name="PurchaseTotal" />
<variable name="OrderId" />
</variables />
</activitystatequery />
是时候再次运行程序了,这次我们将启用第二个控制台客户端应用程序。
运行“TestClient”并复制控制台上显示的 GUID……这是当前订单分配的 ID。现在,在 1 分钟过去(进程自行终止前配置的时间)之前,运行“TestClient2”并粘贴 GUID。这将确认订单,如下所示:
现在切换回 AppFabric Dashboard;您现在应该很熟悉此视图了。已记录两次 WCF 调用和一次 WF 实例调用。
选择跟踪 WF 实例的事件,如下所示:
您将再次被带到通过 AppFabric 监控的事件;然而,现在您还可以跟踪 web.config 文件中配置的变量。为此,滚动直到您到达“Process New Order”活动,您会注意到在该特定时间记录了四个变量,如下所示:
您现在甚至可以根据变量值搜索您的工作流实例。使用“Query Summary”表设置您的搜索查询,如下所示:
相关性
这与 AppFabric 无关,但为了完整起见,仍然值得一提,因为它是在工作流服务开发中一个特别重要的概念。
让我们回顾一下示例 2 的场景:一个客户端向业务流程发送请求以查看目录;稍后它发送另一条消息确认初始目录请求。那么,如果我们有客户端 A 和客户端 B 发出目录请求呢?现在我们有两个进程实例正在等待(已持久化并保存在数据库中)以接收确认消息。当客户端 B 发送确认请求时,会发生什么?引擎如何知道消息应该路由到哪个等待的实例?
用于解决此类情况的概念称为相关性;通过一个唯一的 ID——称为相关 ID——将两个消息(目录请求和请求确认)关联起来的行为。在我们的示例中,您从第一个控制台复制到第二个控制台的 GUID 就是相关 ID;您所做的是为一个特定客户端分配一个 GUID,以便两个请求(由两个不同的控制台应用程序模拟)可以使用此唯一 ID 进行相关。
相关性是在 WF 设计器中相关的 WCF 形状的“Correlations”部分配置的(同样,此处不讨论工作流开发)。
缓存
注意:缓存本身就是一个很大的话题,因此在此进行完整讨论是不可能的。以下内容仅仅触及了 AppFabic 缓存的表面。专门讨论缓存的帖子有望随后发布。
缓存通过将频繁访问的信息存储在内存中来加速应用程序,从而减少数据库访问时间。然而,扩展缓存数据是一个常见问题。将数据存储在内存中使其特定于机器,并且将所有缓存数据集中在一台机器上很快就会造成应用程序瓶颈。
分布式缓存允许将数据分布到多台机器上,现在这是 AppFabric 的一部分。该计划在 AppFabric 之前很久就已发布,项目名称为“Velocity”。
对分布式缓存的完整讨论需要一篇完整的文章;在“更多资源”部分,我将引导您找到一些提供此类信息的资源。但是,总而言之,分布式缓存的工作原理如下:您有一个缓存客户端应用程序(例如,您的 ASP.NET 应用程序,或者在我们的例子中,WF 业务流程),它访问配置在多台机器上的缓存集群。加入缓存集群的所有机器都可以跨它们分布和复制数据,这提供了高可用性的缓存数据。
API 非常简单,在本节中,我们将看到如何使用它来存储和检索数据。
回想一下,在最后一个示例中,您必须从第一个客户端复制 GUID 到第二个客户端;在这里,我们将利用 AppFabric 缓存及其 API 来存储和检索 GUID,而不是这样做。
打开 TestClient 控制台应用程序的“Program.cs”文件。取消注释以下行:
// SetupCache();
// ManageCache(catalog.CatalogId.ToString());
上述方法设置了缓存配置并将 GUID 存储在缓存中。
接下来,打开 TestClient2 控制台应用程序的“Program.cs”文件。注释以下行:
string catalogId = Console.ReadLine();
并取消注释以下行:
//SetupCache();
//string catalogId = GetCache();
上述更改指示第二个客户端从缓存中获取 GUID(由第一个客户端设置),而不是从控制台界面获取。
更多资源
- WF 4 扩展:WF4Extensions.aspx
- 清除 AppFabric 数据库:http://thedotnethub.blogspot.com/2010/05/clean-appfabric-databases.html
- 介绍 Windows Server AppFabric:http://download.microsoft.com/download/7/F/8/7F8BD8A0-EB05-4DB5-A5A4-DD1D3C909A0A/Introducing_Windows_Server_AppFabric.pdf
- Windows Server AppFabric MSDN 页面:http://msdn.microsoft.com/en-us/windowsserver/ee695849.aspx