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

使用 BizTalk Server 2010 和 ESB Toolkit 2.1 的经典发布-订阅解决方案

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2011 年 12 月 7 日

CPOL

4分钟阅读

viewsIcon

37785

downloadIcon

875

本文旨在通过 ESB 工具包为经典的发布-订阅问题提供一种替代解决方案。

您是 BizTalk Enterprise Service Bus (ESB) 2.1 Toolkit 的新手吗?

如果是,请阅读我的 “Hello World” ESB 文章,它将带您入门。

案例研究:一个简单的发布-订阅场景

考虑一种场景,其中需要将 **联系人** 信息发布给多个订阅者。问题在于将联系人更新消息发送给多个订阅者。解决此问题的经典方法是,让 **消息代理编排** 将多个消息放入消息框。然后,这些消息将被发送端口订阅或其他编排消费,以满足量身定制的解决方案。

在本文中,我将尝试使用 ESB 工具包提出一种不同的解决方案。

Publish-Subscribe-CaseStudy.PNG

考虑一种场景,其中需要将自定义 **联系人** 更新消息发送给多个订阅者。这里的订阅者是两个 CRM 系统。其思路是首先将消息转换为 **规范** 形式(如通用联系人)。然后,将此 **规范** 联系人转换为各自的 CRM 特定格式。

自定义联系人消息

自定义 contact 消息**不是**规范形式,这是从应用程序收到的 RAW XML。必须使用转换映射将其转换为规范形式。

MyCustomerContact_XML.PNG

理解行程

在这种情况下使用行程有什么好处?

  • 无需修改现有的 BizTalk 部署配置,即可向行程添加新的订阅者。
  • 可以使用 BRE 规则更改订阅者端点。
  • 可以使用 BRE 规则更改订阅者数据格式(映射)。

Publish-Subscribe-Itinerary.PNG

  1. ESB 入站(On-Ramp):ESB 入站接收消息。这是需要转换为规范形式的自定义联系人消息。
  2. ESB 消息扩展器(Message Extender):此形状用于将自定义联系人消息转换为规范联系人。
  3. ESB 编排扩展器(Orchestration Extender):此形状用于使用编排处理规范联系人,并使用订阅者列表进行分派。解析器(Resolvers)会列出订阅者列表。
  4. ESB 出站(Off-Ramp Extender):出站扩展器用于将规范消息归档到存档文件夹。
  5. ESB 出站(Off-Ramp):BizTalk Server 动态发送端口(也称为 ESB 出站)用于将规范消息放入存档文件夹。

如何在行程中找到转换映射?

MyContact-Canonical.PNG

转换映射是通过行程形状解析器配置中的 BRE 解析器策略 找到的。BRE 策略将如下所示,请注意映射的完全限定名称。

BRE 策略:ContactCanonicalMap

//##Conditions
If Context_Receive_Port_Name == "ContactInfo" and _
    Context_Receive_Location_name == "ContextLocation:FILE"
//##Actions
Set Transform_Type To "MyCustomerSchema.CustomerContact_To_ContactCanonical_Map, _
    MyCustomerSchema, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2710b190689828fa"

BizTalk ESB 兼容的“分派器”编排

步骤 1:消息框绑定

需要一个直接绑定到消息框的逻辑接收端口来接收 ESB 消息。联系人 **规范** 消息由编排接收。

步骤 2:编码编排的核心部分

为简洁起见,编排已分为两个部分。一个用于 **解析器处理**,另一个用于 **推进行程**。

初始化

// Itinerary - Initialize
itineraryWrapper = new Microsoft.Practices.ESB.Itinerary.SerializableItineraryWrapper();
itineraryStepWrapper = 
    new Microsoft.Practices.ESB.Itinerary.SerializableItineraryStepWrapper();

// Itinerary - Assign
itineraryWrapper.Itinerary = 
    Microsoft.Practices.ESB.Itinerary.ItineraryOMFactory.Create(InboundMsg);
itineraryStepWrapper.ItineraryStep = itineraryWrapper.Itinerary.GetItineraryStep(InboundMsg);

// Itinerary - Extract
hasNextService = itineraryWrapper.Itinerary.HasNextService();
resolvers = itineraryStepWrapper.ItineraryStep.ResolverCollection;

// Resolver - Count
System.Diagnostics.Trace.WriteLine("Resolver count: " + 
System.Convert.ToString(resolvers.Count), eventSource);

第一部分:遍历所有解析器

这是编排中最关键的部分。其思路是遍历所有 **解析器** 并将 **转换后** 的消息分配给动态发送端口。

ODX-Sec1.PNG

// Move to retrieve first resolver
resolver = resolvers.Current;

// Pass the resolver configuration to the Resolver mgr for resolution
resolverDictionary = 
    Microsoft.Practices.ESB.Resolver.ResolverMgr.Resolve(InboundMsg, resolver);

// set transport properties
transportLocation = resolverDictionary.Item("Resolver.TransportLocation");
transportType = resolverDictionary.Item("Resolver.TransportType");
mapType = resolverDictionary.Item("Resolver.TransformType");

自定义逻辑:您可以添加自定义逻辑来根据某些规则确定合适的 订阅者

//Retrieve map type from resolution structure
mapCLRType = System.Type.GetType(mapType);
transform(OutboundMsg) = mapCLRType(InboundMsg);
OutboundMsg(*) = InboundMsg(*);

Microsoft.Practices.ESB.Adapter.AdapterMgr.SetEndpoint(resolverDictionary, OutboundMsg);
// Set delivery port address
RoutingDynamicPort(Microsoft.XLANGs.BaseTypes.Address) = transportLocation;
RoutingDynamicPort(Microsoft.XLANGs.BaseTypes.TransportType) = transportType;

第二部分:推进行程到下一步

此操作会将消息发送回行程以执行其他步骤。如果行程没有其他附加步骤,则不会执行该操作。

ODX-Sec2.PNG
OutboundMsg.Body = InboundMsg.Body;
OutboundMsg(*) = InboundMsg(*);

itineraryWrapper.Itinerary.Advance(OutboundMsg, itineraryStepWrapper.ItineraryStep);
itineraryWrapper.Itinerary.Write(OutboundMsg);

System.Diagnostics.EventLog.WriteEntry(eventSource, "Message posted back to ESB.");

步骤 3:在 esb.config 中添加条目

C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.1 下找到 esb.config,找到 XML 标签 itineraryServices 并添加以下内容

    <itineraryservice id="cbd59fc2-e8e0-4d00-ad73-8590938911b2" stage="None" 
scope="Orchestration" type="ContactOperation.Dispatcher, ContactOperation, 
Version=1.0.0.0, Culture=neutral, PublicKeyToken=2710b190689828fa" 
name="ContactOperation.Dispatcher" />

要点:使用 ESB Toolkit 快速转换消息的两种方法是什么?

使用 Transform XLANG 关键字

//Retrieve map type from resolution structure
mapCLRType = System.Type.GetType(mapType);

//Executing a map using transform keyword
transform(OutboundMsg) = mapCLRType(InboundMsg);

注意'mapCLRType' 是一个类型为 'System.Type' 的变量。

使用 'MapHelper.TransformMessage' API 调用

transformedData = Microsoft.Practices.ESB.Transform.MapHelper.TransformMessage
    (InboundMsg.Body.OuterXml, MetadataMsg.Body.TransformationType);

注意'transformedData' 是一个类型为 'System.String' 的变量。

一些需要思考的点

  • **不建议** 在 行程 中使用编排。行程 的设计**不鼓励**使用编排。期待关于更好解决方案的建议,该方案在本文所述情况下避免在行程中使用编排。
  • 任何优雅的设计都清晰地描绘了端到端的邮件流处理,即从源到目的地。行程 是其中一种看待方式。通过使用行程,我们正在模拟端到端的邮件流。
  • 流经 ESB 的每条消息都会附带一个行程。
  • 使用 BRE 解析器可以灵活地在邮件流过程中使用映射。

进一步阅读的参考资料

© . All rights reserved.