Biztalk中orchestration端口的绑定方式多种多样,有以后指定、现在指定、动态、直接绑定四种大的绑定方式,直接绑定中又分为MessageBox、Self Correlating、Panter Orchestration等三种模式,让人看得有些眼花缭乱。
本文试图从一个比较全面、比较深入的视角审视biztalk中的各种端口绑定方式,在描述每种绑定方式的使用方法的同时,试图探究每种绑定方式在biztalk内部的实现方法,看看这么多绑定方式之间是不是在底层的实现机制有哪些共通之处。
首先要介绍一下跟端口绑定密切相关的biztalk的消息订阅机制这个背景,大家知道,biztalk是个基于消息的,通过各种适配器接收消息,处理消息,再通过各种适配器发送消息来完成复杂商业流程的应用平台,消息在biztalk中是核心,控制消息流向的机制就是重点,消息的流转控制分为:消息订阅、消息发布和消息路由三部分。
第一部分简要的介绍一下消息的订阅和发布机制,关于消息订阅发布和路由机制的更详细的信息请参看《深入biztalk消息以及消息订阅发布路由机制(1-4)》
Biztalk中发布消息的主体和订阅消息的主体都被叫做服务,接收端口、发送端口、orchestration等这些可以产生消息的,可以消费消息的主体都是服务。发出消息时这个服务就叫发布服务,接收消息时这个服务就叫订阅服务。
发布服务指的是可以送出消息发布到MessageBox的服务,包括:
接收端口 ―― 从外部接收信息,处理后发布到MessageBox
业务流程 ―― 业务流程启动后可能生成消息发送到发送端口或启动别的业务流程,生成的消息也是发布到MessageBox
要求/响应(Solicit-Response)发送端口 ―― 即双向的要求/响应发送端口。
订阅服务是可以订阅并消费消息的服务,可以作为订阅服务器的服务类型目前有四类:
XLANG/s – 业务流程(orchestration)
Messaging InProcess – 表示发送端口,要求/响应(Solicit- Response)发送端口
MSMQT – MS消息队列
Messaging Isolated – 表示请求/响应(Request-Response)接收端口,目前基本上就是指HTTP和SOAP的Request-Response双向接收端口。
Biztalk中的发布和订阅都是相对MeassagBox而言的,导致消息进入到MeassagBox的就叫发布,根据条件从MeassagBox中取得消息的叫订阅。
当orchestration的一个逻辑接收端口跟一个物理接收端口绑定时,实际上就是产生一个orchestration服务订阅指定的这个物理端口发出的、指定的消息类型的消息。下面来看一下订阅最终反映在biztalk底层,biztalk究竟做了些什么。
最终是反映在biztalk的BizTalkMsgBoxDb数据库中,biztalk会把产生的订阅保存到相关的几张订阅表中。下面的图表示了跟订阅有关的一些表之间的关系。
Figure 1 订阅表关系图
描述订阅消息的订阅服务主体,表示是哪一类服务的哪个具体服务在订阅消息。此表的主要字段为:
nvcName
|
订阅名称
|
uidSubID
|
此订阅的uid
|
uidClassID
|
产生订阅的服务类型,就是上面提到的四种订阅服务之一,每类服务都有一个GUID
|
uidServiceID
|
产生此订阅的具体服务的GUID, 比如订阅服务的是某个orchestration,这里就是这个orchestration的GUID,如果是一个发送端口,那就是这个发送端口的GUID
|
uidInstanceID
|
实例订阅的情况,此字段是产生此订阅的实例的uid
|
uidPredicateGroupID
|
订阅谓词组id
|
uidPredicateGroupID字段跟PredicateGroup谓词组对应表的uidPredicateGroupID字段关联,是一对多的关系。
一个订阅在谓词对应表中有多条记录,表示这个订阅有几组条件组合而成,这几组条件之间的关系是“或”关系。每一组条件中又可以有多个条件组成,通过uidPredicateANDGroupID跟多个谓词表的uidPredicateGroupID字段关联,这也是一对多的关系。
uidPredicateANDGroupID
|
订阅谓词与运算一组的谓词id,每个或运算条件都能由多条与运算的条件组成,由这个字段跟各个谓词表去关联
|
uidPredicateORGroupID
|
订阅谓词,对应到Subscription的uidPredicateGroupID字段。此字段相同的记录表示相应的订阅有多组条件用或运算组成
|
nNumFirstPassPredicates
|
这个或条件组中包含几个与运算条件
|
订阅谓词表有多个,表示订阅的条件。所谓谓词,就是大于、等于、小于、不等于等等这样的比较符,对应每个谓词都有一个谓词表,比如等于(EqualsPredicates)、大于(GreaterThanPredicates)、小于(LessThenPredicates)等等,这些表的结构一样。
uidPropID
|
属性GUID
|
vtValue
|
属性值
|
uidPredicateGroupID
|
谓词组id,此字段跟PredicateGroup表的uidPredicateANDGroupID字段关联
|
这里的属性指的消息上下文中的Property fields(不是Distinguished fields,Distinguished fields没有GUID),包括预定义的系统属性和通过属性架构定义的升级属性,这些属性都有自己的GUID,在订阅谓词表中就是以属性GUID和属性值来表示订阅的条件。
一个订阅条件逻辑看上去可能像这样的:
Subscription:
{
ORGroup0
{
MyPropertSchema.MyCustomProperty1 = True
AND
MyPropertSchema.MyCustomProperty2 = "Purchase Order"
}
OR
ORGroup1
{
BTS.SPTransportID = {29B63190-A
AND
MyPropertSchema.MyCustomProperty3 > 50
}
}
以从接收端口接收进来消息为例。
Figure 2 消息发布
接收适配器接收到入站的信息,在这一步适配器新建消息,并根据入站的信息生成相应的消息部分,多部分的消息在这个阶段形成。
在这个阶段适配器同时将接收位置、适配器类型以及其他内容(与适配器相关)的属性升级到消息的上下文属性。
如果使用的是XMLReceive接收管道,或者在定制的管道中使用了xml拆装器,管道就会把接收进来的消息类型跟已经部署的所有schema进行匹配,如果找到了匹配的架构,就会根据这个架构中设置的自定义的升级属性(Property fields)把消息中的相关字段升级到消息上下文中的Property fields。
消息代理从最终形成的消息中上下文属性中的Property fields提取出来,先把这些属性保存到BizTalkMsgBoxDb数据库的MessageProps 表中,结构如下:
[uidMessageID ]
|
消息的uid
|
uidPropID
|
这个消息中的一个属性,属性都用guid来表示
|
vtPropValue
|
这个属性的值
|
之后,消息代理根据根据这个消息的这些Property fields属性,到上面所说的那些订阅表中去匹配,看是否有哪个服务订阅了这条消息,如果有,就把消息路由到订阅消息的服务,如果没有匹配这条消息的订阅,就会抛出异常,提示这个消息没有订阅者,同时发布这条消息的服务被挂起。
端口绑定本质就是生成订阅,订阅服务订阅发布服务的消息,但是不表示这个发布服务的消息只能给一个订阅服务消费,一个消息可以同时被多个服务订阅,只要这个消息符合订阅条件,消息代理会把订阅把消息发送到所有订阅这个消息的服务实例。
Biztalk提供了这么多的端口绑定方式,实际上都是消息订阅的更高一层的逻辑抽象,底层都是由消息订阅机制来完成绑定功能。
至于各种端口绑定是如何利用消息订阅机制来达到各种绑定目的,下面将分别描述。