Azure 上的 RoutingService






4.89/5 (10投票s)
本文描述了托管在 Windows Azure 上的 WCF4 路由服务的的设计、实现和使用。
目录
特点
- 可管理路由服务
- 将物理终结点映射到逻辑终结点
- 从 Azure 存储管理路由消息
- 基于存储在 Azure 存储中的 XAML 活动的消息中介
- 无服务中断
- 动态添加更多出站终结点
- 动态更改路由规则
- 托管在 Windows Azure 平台
- 使用第三方 Azure 存储浏览器等
- .Net 4 技术
引言
在我以前的文章中,例如 WCF4 的路由管理器、路由服务的 WorkflowChannel 和 WF4 的企业变量,我详细描述了托管在本地 IIS/WAS 服务器上的 System.ServiceModel.Routing.RoutingService
组件的概念、设计和使用。在那些文章中,RoutingService
在业务流程分解和运行时组合中被引入,基于在设计和部署时存储在运行时存储库中的元数据。RoutingService
具有一个独特的功能,允许动态更新配置并重新配置其逻辑映射和入站与出站终结点之间的规则。
本文重点介绍在 Windows Azure 上托管 RoutingService
。我将演示如何通过使用存储在 Azure Blob 存储中的元数据来扩展其在企业应用程序中的使用。您将看到使用存储在 Blob 存储中的工作流活动进行消息中介,跨 Web 角色实例进行广播机制等。所有这些功能都得益于 WCF4、WF4 和 Windows Azure 等出色的 Microsoft 技术。
路由服务使应用程序能够将物理上分离的业务导向型服务,然后使用声明式编程在中央存储库(Blob 存储)中逻辑上(紧密)连接。从架构角度来看,我们可以将路由服务视为私有和公共通信的虚拟集成点(中心)。
下图显示了此架构
如您所见,有一个用于将外部终结点映射到托管服务的逻辑终结点的 RoutingService
Web 角色。换句话说,路由器代表托管服务的虚拟使用者和源,并根据存储在 Blob 存储中的元数据,它可以映射到实际的物理终结点。此架构使我们能够集中存储中的物理终结点,实现托管服务的敏捷配置,与众所周知的路由器终结点进行逻辑连接,并最大程度地减少由于任何原因(例如新服务版本、备份等)进行重新配置连接时的故障。当然,路由器可以连接到 Windows Azure 服务总线,以便在企业和云应用程序之间进行逻辑连接。
RoutingService
的主要关键在于其在运行时更改路由表和规则的能力。当路由服务托管在 Web 角色中时,使用 Azure 存储服务在 Blob 容器中存储路由元数据是一种自然的方式。下图显示了这种情况
如上图所示,由复合应用程序表示的业务模型通过 RoutingService
虚拟化。连接的虚拟化允许将复合应用程序与物理连接隔离开。该应用程序可通过路由器使用众所周知的入口终结点公开。通过此终结点(非类型化合同消息),我们可以根据路由器规则使用任何应用程序服务。由复合应用程序表示的业务流程是小型业务导向型服务(工作器)的容器,这些服务可以通过路由器进行逻辑连接。
WCF4 RoutingService
的可扩展性支持构建远程路由配置。在上图中,路由管理器通过自定义服务行为代表此扩展。在本文中,您将找到一种机制,用于从 Blob 存储获取路由配置,反序列化此配置节并更新运行时路由器表。此外,您还将找到跨多个 Web 角色实例的广播机制。
好了,这就是 RoutingService
的第一个主要功能,例如连接虚拟化。我们可以根据路由器规则和/或消息内容映射、重路由、转发、备份入站消息等。这很棒,感谢 Microsoft WCF 技术。
但是,消息在预处理或后处理中的中介如何?入站消息能否被中介,例如转换其正文、标头等,然后转发到出站终结点?能否在运行时根据管理更改动态完成?
好吧,让我们深入了解这个功能。我们知道,RoutingService
必须在设计时声明所有入站终结点。另一方面,出站终结点可以在运行时声明。从消息处理的角度来看,出站消息可以完全虚拟化和自定义。出站终结点代表转发入站消息的目标终结点,而服务是其托管环境。这是通道工厂的一层。使用标准的消息中介方法,我们需要设计和部署此服务并公开其终结点。此终结点将通过路由器转发的消息的目标。
另一种更高级的方法是从运行时存储库动态调用中介。本文将展示如何以声明式方式设计消息中介,并将其存储在 Blob 存储中,然后由 WCF 自定义通道调用以进行运行时投影。
下图显示了这个场景。
您可以看到,基本上,此方案有两个部分。第一部分是 Blob 存储,它是工作流活动的容器;第二部分是工作流通道。此 WCF 自定义通道仅为通道工厂(无侦听器)实现,支持两种消息交换模式:请求/应答和输出。此自定义通道以 RESTful 方式寻址,例如: http://mysubscription.cloudapp.net/router.svc/Workflow?xaml=Echo 是如何从存储容器调用 XAML 工作流活动 Echo
的示例。请注意,入站消息会传递给 Echo 并返回给调用者。上面的管理工具显示了此消息回路活动。
这很棒,Microsoft WCF4 + WF4 + Azure 技术使我们能够根据业务需求以声明式方式在中介运行时消息。此功能使我们能够将业务模型封装和解耦为部署和运行时两部分,并能够动态管理。
还有一件事。使用 Windows Azure 存储在 Blob 容器中存储运行时资源可以简化和标准化我们的架构。内置的存储服务可以非常方便地访问 Blob 资源。此外,市场上还有第三方 Azure 存储浏览器工具,例如 Azure Diagnostics Manager、Azure Storage Explorer 等,用于管理存储的内容。在本文中,我使用 Azure Storage Explorer,它允许我为特定 Blob 资源(如路由编辑器和工作流设计器)关联自定义编辑器 - 请参见下图
好的,让我们开始介绍在 Windows Azure 上托管的可管理路由服务的概念和设计。
我假设您对 WCF4 路由服务和 Windows Azure 的功能有一定的实践经验或理解。此外,我推荐您阅读我之前提到的文章。
概念与设计
基本上,托管在 Windows Azure 上的 RoutingService
的概念和设计与拥有本地服务器类似,请参阅我关于 WCF4 的路由管理器 的文章。服务行为通过 RoutingManager
自定义行为进行扩展,用于远程处理路由配置。以下代码片段显示了此配置功能
如您所见,上面强制性的 routing
行为对于 RoutingService
是空的,没有任何参数。这是设置 RoutingService
基本行为的必要入口要求,用于空的路由表。路由表的实际内容是在自定义服务行为(如 routingManager
)中完成的。这就是为什么您会在标准行为 routing
中看到所有必需的属性。routingManager
中的附加属性与扩展其用于远程管理路由配置有关。
在服务启动期间,可以从配置文件本地配置路由表,也可以从存储在存储库(Blob、数据库等)中的资源远程配置。此选择由 enableLoader
属性控制。
routingManager
行为中的最后一个操作是将路由信息存储在数据槽中,以便以后用于刷新路由表。以下代码片段显示了此片段
serviceHostBase.Opened += delegate(object sender, EventArgs e) { // make visible for any component in the web role ServiceHostBase host = sender as ServiceHostBase; RoutingExtension re = host.Extensions.Find<RoutingExtension>(); if (configuration != null && re != null) { re.ApplyConfiguration(configuration); lock (AppDomain.CurrentDomain.FriendlyName) { AppDomain.CurrentDomain.SetData(RoleEnvironment.DeploymentId, new RoutingManagerInfo { RoutingExtension = re, RoutingManagerBehavior = this }); } } };
路由管理器合同
路由管理器合同允许在 Web 角色外部与 RoutingService 通信。合同操作设计用于伪广播和点对点模式。以下代码片段显示了 IRoutingManager
合同
[ServiceContract(Namespace = "urn:rkiss/2011/07/ms/core/routing")] public interface IRoutingManager { [OperationContract(IsOneWay = true)] void Broadcaster(string applicationFullName, Guid ticketId); [OperationContract(IsOneWay = true)] void SendStatus(string applicationFullName, Guid ticketId); [OperationContract(IsOneWay = true)] void Refresh(Guid ticketId); [OperationContract(IsOneWay = true)] void Status(Guid ticketId); }
Broadcaster
和 SendStatus
这两个操作合同代表 Web 角色外部事件,主要由管理工具生成,以在多个 Web 角色实例中对 RoutingService
执行操作。众所周知,Azure 当前版本不支持组播或广播传输,因此我们需要使用 HTTP 传输在点对点连接中模拟此过程。跨多个 Web 角色刷新路由表的过程非常简单,并且基于以下场景。
Broadcaster
消息被发送到云,自定义通道中的路由代理会收集所有 Web 角色实例的内部终结点,然后分发器会逐个将 Refresh
消息分发到 Web 角色实例。刷新所有 Web 角色实例中的路由表的过程如下图所示
如您所见,外部入站消息通过硬件负载均衡器传递到 IIS/WebRole 实例。这是一个称为 /Agent
的特定入站终结点,具有将消息转发到自定义通道的路由规则。此自定义通道仅具有通道工厂,用于基于操作标头处理消息。获取所有 Web 角色实例中的内部终结点集合非常简单,如下行代码所示
var endpoints = RoleEnvironment.CurrentRoleInstance.Role.Instances .Select(instance => instance.InstanceEndpoints["RouterManagerEndpoint"]);
其中 RouterManagerEndpoint
是 Web 角色的内部终结点 - 请参见下面的服务定义文件
上面的定义文件还声明了访问运行时存储库的配置设置名称。请注意,Endpoint1
是对硬件负载均衡器可见的公共终结点。Endpoint2
是仅在计算应用程序内部可见的内部终结点。
消息中介
路由器消息中介的概念基于将入站消息转发到自定义出站通道。此自定义通道将调用存储库(Blob 存储)中的 XAML 活动,并在服务 Web 角色中运行其投影。此设计中的关键组件是用于出站终结点的 WCF 自定义通道。有关此自定义通道的概念和设计的更多详细信息,请参阅我关于 路由服务的 WorkflowChannel 的文章。本文具有类似的实现,侧重于存储库,例如 Azure Storage Blob。
上图显示了路由器消息中介的概念。入站消息可以直接转发到出站终结点,而无需任何中介。这是 RoutingService 的标准功能。通过添加 WCF 自定义通道来调用工作流活动,可以将消息转发到此自定义通道进行中介。上图显示了一个单向消息,其中 Send 活动将中介后的消息发送回路由器,以便其转发到出站终结点。此架构的优点是所有组件都松耦合,并且可以通过存储在存储库中的元数据进行声明。换句话说,我们可以随时管理消息中介并将其存储在存储库(Azure 存储)中。例如,合同版本控制、客户端特定合同等。请注意,可以通过内部终结点(此连接不收费)或通过硬件负载均衡器使用外部(公共)终结点将新消息发送回同一路由 Web 角色。对于请求/应答消息交换模式,概念基本相同。中介者将具有 PreProcessor 和 PostProcessor 中介者,最终的 PostProcessor 消息将返回给消息调用者。
总而言之,您可以看到通过使用松散耦合的模式,只需为出站终结点添加 WCF 自定义通道,就可以优雅地扩展 RoutingService
的功能。在本文中,我使用了两个自定义通道,一个用于在多个 Web 角色实例之间广播消息,另一个用于通过路由器进行消息中介。
好的,在实现部分之前,让我们开始在云中使用和测试路由服务。
用法与测试
首先,以下是先决条件:
- Visual Studio 2010 SP1
- Windows Azure SDK v1.4
- 下载本文的软件包
- Azure 存储浏览器
- Windows Azure Platform 账户
- 对 Windows Azure 平台的一些知识和经验
让我们迈出第一步,请下载本文并使用 VS2010SP1 打开它。您应该会看到以下解决方案
解决方案的名称是 AzureEnterpriseVariables
。不要被这个名字迷惑。它是一个通用名称,用于调用存储在 Azure Storage Blob 容器中的资源作为企业变量。基本上,此解决方案中有三个主要的解决方案文件夹。第一个是仅用于测试目的的 Test
文件夹;第二个是 Web/Worker 角色的 Azure 模板,包括服务配置和定义文件;最后一个文件夹实际上是一个使用 RoutingService
的路由管理器的 Web 角色项目。
好的,下一步,请尝试编译此解决方案。它应该没有任何错误。如下图所示,默认情况下配置设置是为模拟器完成的。我将演示在 Azure 模拟器上使用 RoutingService,然后我们可以将其部署到云。
<ServiceConfiguration serviceName="AzureEnterpriseVariables" xmlns="<a href="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration</a>" osFamily="1" osVersion="*"> <Role name="RouterManagerWebRole"> <Instances count="2" /> <ConfigurationSettings> <!-- development --> <Setting name="UseDevelopmentStorage" value="UseDevelopmentStorage=true" /> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" /> <Setting name="RKiss.EnterpriseVariables.Storage.ConnectionString" value="UseDevelopmentStorage=true" /> <!-- azure --> <!--<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=YOUR_ACCOUNT_NAME;AccountKey=YOUR_ACCOUNT_KEY" /> <Setting name="RKiss.EnterpriseVariables.Storage.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=YOUR_ACCOUNT_NAME;AccountKey=YOUR_ACCOUNT_KEY" />--> <!-- options --> <Setting name="RKiss.EnterpriseVariables.RuntimeRepository.ConnectionString" value="tbd" /> <Setting name="RKiss.EnterpriseVariables.Endpoint" value="tbd" /> </ConfigurationSettings> </Role> </ServiceConfiguration>
Azure 模拟器
在对 AzureEnterpriseVariable 项目按 Ctrl+F5 之前,我们需要对开发存储进行一些手动操作。运行 计算模拟器 并在其任务栏图标上单击“开始存储模拟器”。现在我们可以启动 Azure Storage Explorer 并打开 DevStorage
。第一次,我们需要创建新的 BLOB 容器,例如 activities 和 routing - 请参见上面的解决方案包。一旦我们在存储中有容器,我们就可以存储来自解决方案包的资源。
下图显示了一个 activities
容器(ContentType = application/xaml+xm)
下图显示了一个 routing
容器(ContentType = application/xml)
如果上传 Blob 资源时遇到问题,请双击该行以打开 Blob 详细信息对话框,并使用“文本”选项卡粘贴资源内容。此对话框也可用于更改 Blob 属性,例如内容类型等。
Azure Storage Explorer 是一个非常有用的工具,它是免费且开源的,因此我们可以根据需要对其进行修改。当前版本的 Explorer 不具备我在上面的 Blob 详细信息
图片中突出显示的那些功能。此功能允许基于 Blob 内容类型关联任何程序。
在 Test/Editors 文件夹中有两个非常有用的编辑器。第一个是用于创建路由配置的 RoutingEditor:
第二个编辑器是用于创建 XAML 活动的工作流设计器
为了扩展 Blob 详细信息对话框的这两个链接(如 ViewWith...
和 Edit
)的功能,请从 Azure Storage Explorer 下载源代码,并替换此解决方案包中 AzureStoreExplorer
文件夹中包含的文件。顺便说一句,我将请我的朋友 David Pallmann 在下个月更新此工具以支持这些功能。
好了,此时,存储模拟器应该已经准备好进行测试了,换句话说,存储模拟器包含用于活动和路由配置的资源的 Blob 容器。
测试 1 - 消息中介
回到解决方案包。现在我们需要启动计算模拟器。您可以轻松地做到这一点,只需运行项目 AzureEnterpriseVariables。一旦我们有了活动的模拟器(我们的 RouterManagerWebRole 已托管),我们就可以进行测试。
在 Test 文件夹中,您将看到 Simulator 项目。这个 WindowsForm 项目是为了以请求/应答方式或单向方式发送任何消息到终结点而创建的。
启动此 Simulator 程序,然后选择地址 http://127.0.0.1:81/router.svc/Workflow?xaml=Echo. 按下 Invoke 按钮将此消息发送到路由器。您应该会在 Simulator 中看到以下响应
消息已发送到 router.svc/Workflow
终结点,并且基于路由表规则,消息被转发到工作流自定义通道,以便从 Blob 存储获取 XAML 活动 Echo。自定义通道将通过绕过消息返回给调用者(如 Simulator)来调用此活动,因此我们可以在响应面板中看到相同的消息。
太棒了,您可以选择 http://127.0.0.1:81/router.svc/Workflow?xaml=HelloCloud 进行另一次测试。在此测试中,XAML 活动将生成消息 Hello Cloud
。
如果成功,请尝试使用存储容器中的工作流设计器修改或创建您自己的活动。
测试 2 - 路由配置
如前所述,RoutingService 需要声明所有服务终结点以用于入站路由器消息。此服务终结点集合无法在运行时重新配置。下图显示了存储为 Azure Blob 存储中元数据的服务配置
如您所见,RoutingService
中有 4 个终结点。在测试 1 中演示消息中介时,已描述了 endpointWorkflow
终结点。那是将消息转发到工作流通道(请参见客户端终结点 WorkflowAgent
)的入口终结点。
RoutingService 中另一个有趣的终结点是 endpointAgent
。此终结点转发到出站自定义通道 RouterAgent
。通过此路由,我们发送一条消息以供 Web 角色广播器将 Refresh 请求分发到多个 Web 角色实例。
最后,我可以指向开箱即用服务的标准路由消息。在此示例中,路由配置具有一个名为 WeatherService 的客户端终结点。下图显示了此路由配置示例的路由表
请注意,前两行连接,例如 MatchForAgent
和 MatchForWorkflow
,应包含在每个路由表中以供内部使用。第三行(突出显示)显示了公共服务 Weather(http://wsf.cdyne.com/WeatherWS/Weather.asmx)的路由。如您所见,此过滤器使用了带有通配符功能的自定义操作消息过滤器。在此特定过滤器中,操作匹配表达式为 */ws.cdyne.com/WeatherWS/*
。
让我们测试此 MatchForWeather
路由过滤器。启动 Simulator 程序,然后右键单击以加载请求消息资源 Weather.xml。从组合框中选择地址 http://127.0.0.1:81/router.svc,然后按 Invoke 按钮。您应该会看到以下结果
好的,现在让我们动态更改路由配置。基本上,我们需要更新存储,然后向 /Agent
路由器发送一条广播消息。
步骤 1. - 向路由器添加一个新的公共服务,例如: http://www.webservicex.net/ConvertTemperature.asmx
在此步骤中,我们添加了一个新的客户端终结点,例如 ConvertTemperatureService,如下图所示
步骤 2. 向路由器表添加一个新的自定义过滤器 - */www.webserviceX.NET/*
步骤 3. - 发送广播消息以刷新运行时路由表
可以通过 Simulator 发送广播请求消息。请将 Broadcaster.xml 文件加载到请求面板,然后从组合框中选择地址 http://127.0.0.1:81/router.svc/Agent,然后按 OneWay
按钮
步骤 4. - 执行测试
现在,Web 角色实例中的路由器表应该已更新。我们可以再次使用 Simulator 和 ConvertTemperature.xml 资源进行测试。
开发存储到此为止。您应该熟悉如何将任何服务添加到路由器,并使用开发存储库(如计算和存储模拟器)通过 XAML 活动进行消息中介。
好的,让我们继续转移到云。
部署到 Windows Azure
步骤 1. - 第一步是创建存储 Blob 容器,例如 activities
和 routing
。我们可以使用 Azure Storage Explorer 工具来完成此操作。请单击 Add Account
按钮以添加您的 Azure 帐户名称和密钥。之后,使用与为 DevStorage 所做的相同的步骤(创建容器、Blob 等)。此时,您可以将 Blob 资源从 DevStorage 复制到 Azure Storage。
步骤 2. - 对 ServiceConfiguration.cscfg
文件进行更改,例如将节从 development
切换到 azure
设置,并用您实际的值替换 YOUR_ACCOUNT_NAME 和 YOUR_ACCOUNT_KEY。以下代码片段显示了此文件:
<ServiceConfiguration serviceName="AzureEnterpriseVariables" xmlns="<a href="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration</a>" osFamily="1" osVersion="*"> <Role name="RouterManagerWebRole"> <Instances count="2" /> <ConfigurationSettings> <Setting name="UseDevelopmentStorage" value="UseDevelopmentStorage=true" /> <!-- development --> <!--<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" /> <Setting name="RKiss.EnterpriseVariables.Storage.ConnectionString" value="UseDevelopmentStorage=true" />--> <!-- azure --> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=YOUR_ACCOUNT_NAME;AccountKey=YOUR_ACCOUNT_KEY" /> <Setting name="RKiss.EnterpriseVariables.Storage.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=YOUR_ACCOUNT_NAME;AccountKey=YOUR_ACCOUNT_KEY" /> <!-- options --> <Setting name="RKiss.EnterpriseVariables.RuntimeRepository.ConnectionString" value="tbd" /> <Setting name="RKiss.EnterpriseVariables.Endpoint" value="tbd" /> </ConfigurationSettings> </Role> </ServiceConfiguration>
步骤 3. - 重新编译解决方案,然后单击 Publish AzureEnterpriseVariables
项目。以下对话框将提示您在 Azure 上部署项目。
单击 OK 按钮后,Visual Studio 2010 SP1 中的 Windows Azure Activity Log 视图面板将显示,请参见下图
注意,使用其他选项,例如 Create Service Package Only
,VS 将创建用于手动部署的包,例如通过 Azure 门户。
步骤 4. 测试
基本上,上面部分中描述的所有测试都可以通过将模拟器地址 127.0.0.1:81
替换为实际的 Azure 地址 YOUR_DNS_PREFIX.cloudapp.net
来重复。
实现
在本节中,我将描述一些与 Azure 相关的有趣代码片段。以下是从 Azure Blob 存储或 Azure Storage 模拟器获取资源的 Snippet
public static string GetResource(ResourceType resourceType, string settingName, string container, string name) { string connectionString = RoleEnvironment.GetConfigurationSettingValue(settingName); if (settingName == StorageSettingName || settingName == "UseDevelopmentStorage") { #region Azure Storage var account = CloudStorageAccount.Parse(connectionString); var blobClient = account.CreateCloudBlobClient(); // container var blobContainer = blobClient.GetContainerReference(container); if (blobContainer == null) throw new Exception("..."); var cloudBlob = blobContainer.GetBlobReference(name); if (cloudBlob == null) throw new Exception("..."); config = cloudBlob.DownloadText(); #endregion } // ... }
第一步是从 RoleEnvironment 获取配置设置值。基于此 connectionString
,我们可以获得一个 Azure 帐户。一旦我们有了 Azure 帐户,我们就可以检索容器和特定的 Blob 资源。如您所见,这是一种非常直接的实现,代码量最少。感谢 Microsoft.WindowsAzure 命名空间。
下一个有趣的实现是用于跨多个 Web 角色实例刷新运行时路由表的广播消息。路由器代理收到的消息被转发到出站自定义通道。以下代码片段是其广播消息的一部分
if (action == RoutingManagerDefaults.ActionBroadcaster) { #region Broadcaster string applicationFullName = body.Element(RoutingManagerDefaults.ApplicationFullName).Value; var endpoints = RoleEnvironment.CurrentRoleInstance.Role.Instances.Select(instance => instance.InstanceEndpoints["RouterManagerEndpoint"]); foreach (var endpoint in endpoints) { ChannelFactory<iroutingmanager> factory = null; try { EndpointAddress address = new EndpointAddress(String.Format("http://{0}/Router.svc/Agent", endpoint.IPEndpoint)); Binding binding = new BasicHttpBinding(BasicHttpSecurityMode.None); factory = new ChannelFactory<iroutingmanager>(binding); IRoutingManager channel = factory.CreateChannel(address); channel.Refresh(ticketId); factory.Close(); } catch (CommunicationException) { if (factory != null && factory.State == CommunicationState.Faulted) factory.Abort(); factory = null; } catch (Exception) { if (factory != null && factory.State != CommunicationState.Closed) factory.Close(); factory = null; } } #endregion } </iroutingmanager></iroutingmanager>
首先,我们需要获取所有 Web 角色实例的内部终结点集合。之后,我们可以创建一个具有特定终结点地址的代理并触发 Refresh
消息。请注意,此消息直接发送到 IIS VM 实例,因此此连接和传输没有额外费用。
还有一个实现示例。为了基于消息操作简化路由消息,我创建了一个自定义操作消息过滤器,其中包含通配符表达式。以下代码片段显示了其实现
public class ActionMessageFilter : MessageFilter { public string WildcardExpression { get; set; } public ActionMessageFilter(string wildcardExpression) { this.WildcardExpression = wildcardExpression; } public override bool Match(System.ServiceModel.Channels.Message message) { string pattern = "^" + Regex.Escape(this.WildcardExpression).Replace(@"\*", ".*").Replace(@"\?", ".") + "$"; bool isMatch = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline).IsMatch(message.Headers.Action); return isMatch; } public override bool Match(System.ServiceModel.Channels.MessageBuffer buffer) { throw new NotImplementedException(); } }
结论
总而言之,本文介绍了一种基于托管在 Windows Azure 上的 WCF4 路由服务的可管理路由器。可管理路由器允许从存储在存储库(Azure Blob 存储)中的集中式逻辑模型动态更改路由规则。路由器代表用于将逻辑终结点映射到物理终结点的虚拟化组件,并且是模型驱动的分布式架构中的基本组件。本文还展示了如何使用存储在 Azure Blob 存储中的 WF4 Activity XAML 资源来中介消息。对 Azure 存储所做的所有更改都可以传播到多个 Web 角色实例。
参考文献
[1] Overview of Creating a Hosted Service for Windows Azure
[2] Creating a Hosted Service for Windows Azure
[3] Windows Azure
[5] WCF4 的路由管理器
[6] WF4 的企业变量