65.9K
CodeProject 正在变化。 阅读更多。
Home

多租户应用程序元数据驱动 (使用 WCF 4.0, WWF 4.0)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2013 年 9 月 11 日

CPOL

13分钟阅读

viewsIcon

18904

downloadIcon

797

多租户应用程序元数据驱动 (使用 WCF 4.0, WWF 4.0)

引言

多租户通过 Windows Workflow Foundation 4.0 和 Windows Communication Foundation 4.0 实现。此处概念验证 (POC) 将满足以下所有提及的要求。动态加载不同的工作流进程(占应用程序的 20%)。对不同工作流进程的任何更改都不会影响核心工作流进程(占应用程序的 80%)。回归测试、租户上载的持续时间/成本最少。业务规则的外化、应用于业务规则的多租户也是此处的重点。

背景

  • 多个应用程序的痛点 ·
  • 大量冗余,复用性差
  • 代码更改在多个版本中进行,导致增强和维护困难
  • 多个交付/支持团队执行类似工作
  • 多平台 TCO(总拥有成本)高
  • 租户上载成本高
  • 租户上载不快速
  • 多个 IT 支持团队
  • 即使更改仅限于一个租户,也需要对所有租户进行回归测试

解决方案

动态进程流

  • 租户特定工作流进程
  • 每个租户一个程序集,包含不同的进程定义
  • 将进程调用决策外化,独立于工作流程序集
  • 租户不同程序集的独立部署
  • 基于元数据的动态加载和调用不同程序集
  • 元数据驱动的工作流进程
  • 利用的 WWF 4.0 和 WCF 4.0 功能
  • 使用 WWF 4.0 定义的工作流进程
  • WCF 拦截和服务定义

动态业务规则

  • 租户特定业务规则
  • 规则版本控制
  • 松耦合业务规则
  • 将规则定义部署到数据库以供每个租户使用
  • 元数据驱动的业务规则
  • 动态加载和执行规则
  • 定义规则的 Windows 应用程序
  • WWF Business Rules Engine (BRE) 执行规则

建议方法 ·

方法 1:使用 WWF 4.0 中的新功能“工作流即服务”。此工作流经过编排,用于加载核心工作流进程和租户的不同工作流进程。但这在 WWF 4.0 中存在局限性,因此该方法被放弃。局限性在于:WCF 拦截无法在客户端和工作流服务之间实现,以拦截租户 ID。此局限性已在 WWF 4.5 中得到修正。·

方法 2(已考虑):使用 WCF 服务使用 WWF 4.0 实现加载核心工作流进程和不同工作流进程。不同工作流进程根据租户 ID 动态加载。租户 ID 从客户端跨 WCF 服务(调用工作流进程的服务)以及工作流编排中使用的其他 WCF 服务进行拦截。

业务规则通过 WWF Business Rules Engine (BRE) 从工作流进程调用的 WCF 服务执行。业务规则定义根据租户 ID 从数据库动态加载。因此,规则的松耦合得以实现。

应用程序架构

  1. 多租户 WCF 服务:客户端调用 WCF 服务,在 POC 中(服务名称- FacilityService,方法 - CreateFacility)。租户 ID 通过 WCF 拦截传递。服务引用了 dll - MetadataFetch,VariedProcessLoader。
    注意:服务启用了 AspNet Compatibility 以利用 asp.net 缓存。
  2. Metadata Fetch:这是一个 .NET 程序集,它与 SQL 数据库通信,根据租户 ID 获取元数据,以决定是调用核心工作流进程还是不同进程。如果某个租户有元数据(租户映射到命名空间和类名(工作流进程名称)),则会加载并调用该特定不同进程,否则调用核心工作流进程。
  3. Varied Process Loader:这是一个 .NET 程序集。如果 MetadataFetch 程序集返回特定租户的命名空间和类名(工作流进程名称)。那么将加载并使用适当的输入调用相关的不同工作流进程程序集。
  4. Core Workflow Process (.NET Assembly):这是一个 .NET 程序集,包含 XAML 文件(工作流进程定义)。如果任何租户没有定义特定的不同进程,则调用默认的相关核心工作流进程。
  5. Varied Workflow Process (.NET Assemblies):这些是 .NET 程序集,包含 XAML 文件(工作流进程定义)。每个有不同工作流进程的租户都在一个程序集中定义,即每个租户一个程序集。每个程序集将根据需求包含多个 XAML 定义。这些程序集(dll)被部署到一个文件夹(此处为“D:\DeployedXaml”),Varied Process Loader 从该文件夹动态加载程序集并调用相应的工作流。
  6. Consumption WCF Services:这些是多个 WCF 服务。(此处有 3 个服务 - FacilityValidation,IncomeTax 和 SalaryDetails)。它们实现业务规则。SalaryDetails 通过 Workflow Business Rules Engine 调用业务规则。
  7. External rule set Service:这是一个工作流业务规则执行组件。
    它包含用于创建/修改规则的 Rule Editor。规则集(规则定义)与详细信息(例如主要版本(租户),次要版本)一起保存到数据库。规则是在“规则库”中定义的 Target 对象(客户端)上创建的。ExternalRuleSetService 将从数据库获取规则集定义,并使用 Workflow BRE API 执行它们。Target 对象程序集(dll)被部署到一个文件夹(此处为“D:\DeployedXaml”),规则集引用了该文件夹。
  8. WCF Interception:租户 ID 通过 WCF 拦截在整个应用程序中进行拦截。
    注意:使用 Asp.NET 缓存将其存储在服务内。

Using the Code

解压文件后,需要进行以下配置

  1. 在 D:\DeployedXaml 中创建文件夹:这是部署 dll(不同工作流进程,规则库)的文件夹路径
    注意:这已在项目属性->生成后置生成事件中配置。
    要更改路径,请在项目属性和配置文件(web.config 或 app.configs 的“XamlPath”键)中进行相应更改。
  2. 所有已部署的消耗服务(WCF 服务)的路径已在客户端消耗服务的配置文件(Web.config)中更新。
  3. 配置数据库 - 可以使用 Rules mdb 和日志文件,或者创建一个名为“Rules”的数据库,然后在 SQL Management Studio 中运行附加的数据库脚本。
  4. MulitenancyWorkflowService 项目:web.config 包含任何进一步修改的数据库配置。
  5. 运行应用程序,使用此处附加文档中指定的数值

附加了作为测试一部分执行的场景。

项目结构

  • WCF Service (MulitenancyWcf):客户端调用 WCF 服务。该服务调用“CreateFacility”工作流进程(根据租户 ID,可以是不同的或核心的)。
  1. 服务名称:FacilityService
  2. 操作名称:CreateFacility
  3. 请求数据契约:FacilityRequest 对象,在 DataContractLibrary 中定义。
  4. 响应数据契约:FacilityResponse 对象,在 DataContractLibrary 中定义。
  5. 配置:Web.config
  6. RuleSetStoreConnectionstring:包含数据库连接字符串配置
  7. Services/Bindings:包含 WCF 拦截和 WCF 服务消耗相关的配置
  8. ServiceHostingEnvironment:启用了 aspNetcompatibility 模式,该模式启用了 ASP.NET 缓存

<connectionStrings>
    <add name="RuleSetStoreConnectionString" connectionString="Initial Catalog=Rules;
    Data Source=localhost;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
  </connectionStrings>
 
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>
  • 工作流程

核心工作流:这是一个 .NET 程序集,包含所有默认或核心工作流的定义文件(XAML)。这些工作流适用于所有没有定义不同工作流进程的租户。此 dll 在 Multitenancy WCF Service 中被引用。

上图是核心工作流的项目,当前 POC 已定义核心工作流(CreateFacility.xaml)。CreateSecurity 和 UpdateSecurityStatus 仅是空的 Wokflow 文件。 上图是 CreateFacility 工作流定义,此工作流定义调用 3 个 WCF 服务 - FacilityValidation,SalaryDetails 和 IncomeTax。根据 WCF 服务的输出,创建工作流响应。

不同工作流:这些是 .NET 程序集,包含每个租户的不同工作流定义文件。每个租户都有一个单独的程序集,其中定义了不同工作流进程(如果存在变体)。

以下是不同工作流进程的项目结构。每个租户都有一组不同的进程。对于

    • Tenant1 -(WorkflowTenant1)- CreateFacility 是不同的工作流进程,CreateSecurity UpdateSecurityStatus 仅是粗略示例,用于说明可以在单个租户中添加多个不同的工作流进程。
    • Tenant2 -(WorkflowTenant2)- 定义了不同的工作流进程 CreateFacility
    • Tenant3 -(WorkflowTenant3)- 没有为 CreateFacility 定义不同的工作流进程。

注意:不同工作流进程仅在存在相同核心工作流进程时才存在。

  • DataContract Library:这是一个被所有项目引用的 .NET 程序集。它包含 WCF 服务和工作流进程的数据契约(请求和响应),定义如下。
  • Activities:Data Contract Library 还包含代码活动,这些活动用于工作流定义中,其中输入被操作(数据类型转换)并创建响应。

  • Decision Library:这是一个 .NET 程序集,包含用于处理元数据工作流决策和不同工作流进程加载器的类。

    Metadata Fetch:这是一个 .NET 程序集,它与 SQL 数据库通信,根据租户 ID 获取元数据,以决定是调用核心工作流进程还是不同进程。如果某个租户有元数据(租户映射到命名空间和类名(工作流进程名称)),则会加载并调用该特定不同进程,否则调用核心工作流进程。

    Varied Process Loader:这是一个 .NET 程序集。如果 Metadata Fetch 程序集返回特定租户的命名空间和类名(工作流进程名称)。那么将加载并使用适当的输入调用相关的不同工作流进程程序集。

  • Interceptors

    1. Service Interceptors:通过实现 IDispatchMessageInspector 接口来实现 WCF 拦截。
      IDispatchMessageInspector.AfterReceiveRequest(ref Message request, 
      IClientChannel channel, InstanceContext instanceContext) 

      AfterReceiveRequest 事件从消息体中提取租户 ID,并将其保存在 ASP.NET 会话中,供服务后续使用。

      注意:它们涉及相关的配置(App.config/web.config)更改。

    2. Client Interceptors:通过实现 IClientMessageInspector 接口来实现 WCF 拦截。
      IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
       System.ServiceModel.IClientChannel channel) 

      BeforeSendRequest 事件在向服务发出任何请求之前被调用。在此,租户 ID 从当前 ASP.NET 会话中提取,因此租户 ID 被传递到消息头中。

      注意:它们涉及相关的配置(App.config/web.config)更改。

  • Consumption Services:这些是工作流使用的 WCF 服务。

    · FacilityValidation :客户端输入的 FacilityAmount 使用 FacilityValidation 服务中的 GetFacilityValidationAmount 操作与金额进行验证。根据 facilitytype 返回验证金额。

    · SalaryDetails:调用 SalaryDetails 服务中的 GetClientSalary 操作。此处执行使用 Workflow Rules Editor 定义的业务规则。业务规则可以独立于 WCF 服务进行编辑。规则的任何更改都不会在部署方面影响此 WCF 服务。

    · IncomeTax:调用 VerifyTax 操作来验证税款。业务规则只是在此处编码。

  • Rules

    ExternalRuleSetLibrary:这只是一个数据实体,用于从数据库访问的规则集信息。·

    ExternalRuleSetService:包含与数据库通信的类,以根据指定的规则集名称、租户 ID/主版本、次版本获取规则集。它还包含使用 WWF 4.0 BRE API 执行规则的类。·

    RulesLibrary:包含规则定义的实体类或目标对象。·

    ExternalRuleSetTool:这是一个用于创建/修改规则的接口。该工具将规则定义保存到数据库。

    下面的 Rule Editor 来自以下链接:http://msdn.microsoft.com/en-us/library/bb442824.aspx

    在“Rule Store”菜单下,您可以从数据库加载可用的 RuleSets,并将修改后的 RuleSets 保存回存储。应用程序配置文件为 RuleSet 数据库提供了数据库连接字符串。启动工具时,它会自动从配置的数据库加载 RuleSets。

    RuleSet 工具为主版本(此处为租户 ID)和次版本号分配给 RuleSets,允许您同时维护和存储多个版本(该工具除了版本控制功能外,不提供任何锁定或其他配置管理功能)。使用该工具,您可以创建新的 RuleSet 版本或删除现有版本。单击“New”时,该工具会创建一个新的 RuleSet 名称并将版本号设置为 0.0。复制某个版本时,该工具会创建选定 RuleSet 版本的副本,包括其中的规则,并分配新的唯一版本号。这些版本号基于现有 RuleSets 的版本号。您可以使用表单上的相关字段更改 RuleSet 名称和版本号。

    注意:版本 0 - 将是默认的 RuleSet,如果数据库中不存在租户映射,则会执行该 RuleSet。

    单击“Edit Rules”时,将启动 RuleSet 编辑器,如下图所示

    这是 Windows Workflow Foundation Visual Studio 插件中包含的编辑器对话框的重新托管。它提供了相同的功能,包括 Intellisense 支持。规则是针对与工具中的 RuleSet 相关联的目标类型(例如工作流)编写的;单击主工具对话框中的“Browse”时,将出现 Workflow/Type Selector 对话框,如下图所示。

    您可以使用 Workflow/Type Selector 对话框指定一个程序集和一个该程序集中的特定类型。该类型是编写(和运行)规则的目标类型。在许多情况下,目标类型是工作流或其他活动类型。但是,您也可以针对任何 .NET 类型运行 RuleSet。

    程序集文件的路径和类型名称与 RuleSet 一起存储在数据库中,因此当从数据库检索 RuleSet 时,该工具会尝试自动加载目标类型。

    单击 Workflow/Type Selector 对话框中的“OK”时,它会验证所选类型与 RuleSet 是否匹配,以确保目标类型包含规则引用的所有成员。

    有关该工具的更多详细信息,请参阅上面提到的链接。

Data Model

  • TenantAssemblyMap - 此表包含租户映射到不同工作流进程(程序集)的数据。
  • Tenant- 此表包含租户名称和 ID。
  • AssemblyDetails - 此表包含每个租户的工作流进程定义所在的程序集名称。这是调用工作流进程所需的工作流元数据。
  • NamespaceDetails – 此表包含程序集中定义的工作流进程的命名空间详细信息。这也是调用工作流进程所需的工作流元数据。
  • ClassDetails – 此表包含程序集中定义的工作流进程的类详细信息。这也是调用工作流进程所需的工作流元数据。
  • Rule Set – 此表包含带有版本号的规则定义。表中的 MajorVersion 列是 TenantId。

关注点

关注点将是整个多租户概念。有几种模式用于实现此目的。我们尝试使用 Microsoft 工具来实现这一点。

历史

在 Infosys Technologies 工作的 Sundararajan Thyagarajan 提出了关于多租户的想法。这是基于一个领先的保险项目中关于多租户的几项要求。可能需要进一步研究该方法的性能优势,以及研究使用 MEF(Managed Extensibility Framework)组合是否可以实现多租户概念。此外,还需要对文章中描述的因 WWF 4.0 局限性而失败的方法 1 进行进一步研究。

© . All rights reserved.