当前位置: 首页 > 编程日记 > 正文

深入biztalk消息以及消息订阅发布路由机制(二)-消息订阅【转】

一.消息订阅

订阅消息的主体叫订阅服务器,订阅服务器是可以订阅并消费消息的服务,可以作为订阅服务器的服务类型目前有四类,在BizTalkMgmtDb管理数据库中的adm_ServiceClassName字段列出了所有可以作为订阅服务器的服务类型,包括:

XLANG/s – 业务流程(orchestration

Messaging InProcess – 表示一般的发送端口、Solicit- Response发送端口

MSMQT – MS消息队列

Messaging Isolated –表示请求/响应(Request-Response)接收端口,目前基本上就是指HTTPSOAPRequest-Response双向接收端口。

每种服务都有自己的id,为16字节GUID的形式(biztalk中对象的标识id都采用GUID的形式,biztalk数据表中大量的使用到这种16字节的统一标识数据,sql server中的uniqueidentifier 数据类型,就是用来存放GUID类型的数据)

1. 消息订阅主体

消息订阅最后体现在BizTalkMsgBoxDb数据库的反应订阅主体的Subscription表(表示是哪个服务产生的这个订阅)和反应订阅条件的一组谓词表中(表示这个订阅的具体条件,用来判断哪些消息是符合这个订阅的)。

先来看一下Subscription表的主要字段含义,这个表指示了订阅消息的具体是哪一个服务:

nvcName ―― 此订阅的名称

uidSubID ―― Guid类型,此订阅的uid

nvcApplicationName ――订阅服务器所属主机实例名,路由消息时不同的主机实例将调用不同的存储过程处理。

uidClassID ―― 产生订阅的服务类型,adm_ServiceClass 服务表UniqueId字段的外键

uidServiceID ―― 产生此订阅的具体服务,根据uidClassID服务类型的不同,对应到不同类别的服务.如果uidClassID指示的是XLANG/s,则对应的是业务流程,此字段对应到bts_Orchestration表中的uidGUID字段。为Messaging In-Proc时,表示由发送端口订阅消息,对应到bts_SendPort表中的uidGUID MSMQt时有点混乱,但大多数情况下也在bts_SendPort table表中体现。实例订阅时,服务实例是请求/响应端口时的这个字段并不是接收端口的guid也不是接收位置的guid,不清楚这个guid跟什么对应。哪位知道的朋友能不能告知一下。

uidInstanceID ―― 实例订阅时的订阅消息的服务实例的guid。激活订阅时此字节为空。

Biztalk中存在两类订阅:激活订阅和实例订阅。激活订阅收到执行订阅的消息后,该消息创建新的订阅服务器实例来处理这个消息,一般的订阅都属于这类订阅。实例订阅将指示执行订阅的消息应路由到已在运行的订阅服务器实例。有一种服务会产生实例订阅的情况即“Messaging Isolated ”,这类服务的典型就是请求/响应接收端口,这类服务其实可以产生两个订阅。先是请求/响应接收端口的接收部分,这部分相当于消息分布服务器,可以由其他订阅服务器来订阅这个消息,比如一般是业务流程的一个接收形状绑定这个端口,实际上就是订阅了这个端口接收到的消息。这个接收端口服务实例建立后,把收到的消息发送到MessageBox。然后请求/响应接收端口的响应部分,这部分相当于订阅服务器,如果这部分绑定到业务流程的一个发送形状,这个接收端口服务实例会生成一个实例订阅,这个字段就用来存放这个接收端口服务实例的guid,表示还是由这个服务实例来处理返回的消息。这样,就完成了一个从接收到响应的一个往返过程。实例订阅是由服务实例生成的订阅,所以在产生实例订阅收到消息被放入到消息队列后,会在订阅表中把这个实例订阅删除。

还有一种情况会形成实例订阅,orchestration中使用相关集时,一个orchestration实例的一个端口发送消息出去,返回的消息仍然由这个orchestration实例的一个接收形状接收。这里也有一个orchestration实例的订阅发出去的消息的实例订阅。

uidPortID ―― 订阅服务类型为XLANG/s,此字段表示业务流程中接收消息的端口形状,对应bts_orchestration_port表中的uidGUID字段。对于 MessagingMSMQt,这个字段指示使用发送端口的主通道还是辅助通道。先根据uidServiceIDbts_SendPort表中找到相应的端口,然后用bts_SendPort表的nID bts_sendport_transport表的nSendPortID 关联。uidPortIDbts_sendport_transport表的uidGUID 关联,就能确定使用哪个发送端口的通道。

fEnabled ―― 此订阅的状态,0 ―― 禁用;1 ―― 活动;2 ―― 停用

uidPredicateGroupID ―― 订阅谓词组id

2. 消息订阅条件(谓词)

一个订阅的主体存在Subscription表中,相应的订阅条件则分别存在一组谓词表中,不同的类型的条件放在不同的表中,比如等于的条件放在EqualsPredicates中,小于的条件放在LessThenPredicates中,一共有以下这么多的谓词表:

l         BitwiseANDPredicates

l         EqualsPredicates

l         EqualsPredicates2ndPass

l         ExistsPredicates

l         FirstPassPredicates

l         GreaterThanOrEqualsPredicates

l         GreaterThanPredicates

l         LessThenOrEqualsPredicates

l         LessThenPredicates

l         NotEqualsPredicates

这些表的基本结构都是一样的,都是按照什么属性(属性的GUID)+谓词(等于、大于、小于。。。)+属性的值的形式出现。看一下这些表的数据结构:

uidPropID ―― 属性的guid。所有属性都有自己的guid,包括类似接收端口、接收适配器类型等系统属性,或者从schema升级的属性。

vtValue ―― 属性的值

uidPredicateGroupID ―― 一组谓词的id,一个订阅可以有多个条件谓词,这个字段表示同一组的条件,条件也可分为或条件和与条件,条件的组合通过PredicateGroup表在Subscription表和各个谓词表之间进行组合。

看一下PredicateGroup表的结构:

uidPredicateORGroupID --订阅谓词,对应到SubscriptionuidPredicateGroupID字段表示是与这个订阅相关的条件。此字段相同的记录表示相应的订阅有多组条件用或运算组成。

uidPredicateANDGroupID --订阅谓词与运算一组的谓词id,每个或运算条件都能由多条与运算的条件组成,最终由这个字段跟各个谓词表去关联。

nNumFirstPassPredicates --这个或条件组中包含几个与运算条件。


这个图中显示了一个发送端口设置筛选条件(就是设置订阅条件)的示例。从上可以看出这个订阅实际上设置了两组或运算的条件,其中第一组内又包含了两个与运算的条件。在
PredicateGroup表中的表现就是对应这个订阅的有两条uidPredicateORGroupID相同的记录,表示两组或运算条件,相应的uidPredicateANDGroupID字段对应到EqualsPredicates谓词表中,其中有一个对应两条记录,一个对应一条记录。

3. 消息订阅过程

下面的图是涉及到订阅部分数据库表的主要结构和相互关系。各字段的含义上面两节基本都有描述了。


下面看一下
biztalk中两种订阅方式的各自如何产生订阅的:

3.1.              激活订阅

一般情况下,业务流程、发送端口和MSMQ这三类服务产生的订阅是激活订阅。这种订阅是被订阅的消息根据订阅条件新建订阅消息的服务主体,即新建一个服务实例,然后由这个服务实例处理订阅的消息,服务实例将消息处理完毕后,这个实例就算完成任务。

业务流程订阅一般表现形式是业务流程的接收端口跟物理端口绑定。其实它的订阅主体是这个业务流程的这个接收端口。条件是绑定的发送端口发送来的消息。

发送端口订阅一般可以是发送端口绑定到业务流程的一个发送端口。也可以是发送端口直接订阅由接收位置接收的消息,在发送端口的筛选器中可以根据消息的各种属性(包括系统属性和从schema升级的属性)来定义订阅的条件,比如某个消息的哪个升级属性大于某个值时。

以业务流程绑定一个物理接收端口为例说明:

业务流程跟一个物理接收端口绑定后,实际进行的操作是产生一个订阅。就是在Subscription表中生成一条记录表示订阅的主体,然后在一组谓词表中生成相应的订阅条件。

订阅主体就是这个业务流程的绑定的端口。在Subscription表中生成记录,字段uidClassIDXLANG/s业务流程服务的guid,表示订阅主体的服务类型是业务流程。uidServiceID字段是订阅的具体业务流程的guid(对应bts_Orchestration表)。uidPortID字段是这个业务流程中接收端口的guid(对应bts_orchestration_port表),uidPredicateGroupID字段是订阅谓词组id,表示跟这个订阅相关的谓词表中的记录。

订阅主体在Subscription表生成记录后,然后把订阅的条件要记入到相应的谓词表中。本例中端口绑定的情况,会产生两个条件,一个是接收端口id等于绑定的那个接收端口,形式为:http://schemas.microsoft.com/BizTalk/2003/system-properties. ReceivePortID == {9DB16A5F-ADD7-4CF2-9B9A-D7924426DD18};另一个是消息类型是业务流程接收端口指定的消息类型,形式为:http://schemas.microsoft.com/BizTalk/2003/system-properties.MessageType == http://EAISchemas.Request#Request

这两个条件中都含有“system-properties”,表示是系统属性,这两个又都是等于条件,所以都记入EqualsPredicates谓词表中。所有的属性都有guid,系统属性有预设的guid,升级属性前面章节已经讲到,每个升级的属性都会生成一个guid(这就是为什么升级的字段可以用来路由消息,而可分辨字段不可以用来路由消息的原因,可分辨字段没有guid)。所以这两个条件在谓词表中的表现是,两属性guid代表的属性分别等于什么值。

3.2.              实例订阅

这种订阅由服务实例产生,并放入到订阅表中。当消息路由到消息队列后,会将订阅表中的实例订阅记录删除。

一般来讲Messaging Isolated(表示物理请求/响应类型的接收端口)这类服务会用到实例订阅,下面就这个为例说明:

请求/响应类型的接收端口,一般是由业务流程订阅这个端口的请求部分的消息,经过处理后返回消息,这个端口的的响应部分再订阅这个返回的消息,处理后返回给请求端。

请求部分的订阅是激活订阅,不再赘述。

响应部分是实例订阅,是由请求部分收到消息后新建Messaging Isolated服务实例后,这个服务实例在订阅表中建立的一个订阅,这个订阅其他部分跟激活订阅一致,就是在Subscription表中的uidInstanceID字段填入这个服务实例自身的guid,表示这是实例订阅,订阅主体就是这个服务实例。

当消息路由到这个实例订阅的消息队列后,这个实例订阅的使命就完成了,被从订阅表中删除,这个过程在下面消息的发布和路由中还有叙述。

4. 端口绑定的本质

端口绑定本质就是生成订阅,订阅服务器订阅发布服务器的消息,但是不表示这个发布服务器的消息只能给一个订阅服务器消费,一个消息可以同时被多个服务订阅,只要这个消息符合订阅条件,消息代理会把订阅把消息发送到所有订阅这个消息的服务实例。

转载于:https://www.cnblogs.com/cxd4321/archive/2007/09/26/906856.html

相关文章:

poj1625Censored!(AC自动机+dp)

链接 第一次做这种题目,参考了下题解,相当于把树扯直了做DP,估计这一类题都是这个套路吧。 状态方程dp[i][next] dp[i][next]dp[i][j] ;dp[i][j]表示长度为i的第J个结点的时候满足题意的num,next为当前j点所能走到的下一个合法的…

图解5G NR帧结构

子载波间隔 与LTE(子载波间隔和符号长度)相比, NR支持多种子载波间隔(在LTE中,只有15 Khz这种子载波间隔)。 在3GPP38.211中,有关于NR子载波间隔类型的总结。 具体的子载波间隔类型如下图所示&a…

(C++) A+B 输入输出练习IV 每行的第一个数N,表示本行后面有N个数。 如果N=0时,表示输入结束,且这一行不要计算。

#include<cstdio>/* 4 1 2 3 4 5 1 2 3 4 5 0 */int main(){int n,a;while(scanf("%d",&n),n){int sum 0;for(int i 0;i<n;i){scanf("%d",&a);sum a;}printf("%d\n",sum); }return 0;}

jQuery与其它库冲突的解决方法(转)

原文出处&#xff1a;http://www.jb51.net/article/24014.htm 在jQuery库中&#xff0c;几乎所有的插件都被限制在它的命名空间里。全局的对象都很好地存储在jQuery命名空间里&#xff0c;因此当把jQuery和其它javascript类库一起使用时&#xff0c;不会引起冲突. (注意&#x…

ASP.NET 下载文件方式

protected void Button1_Click(object sender, EventArgs e){/*微软为Response对象提供了一个新的方法TransmitFile来解决使用Response.BinaryWrite下载超过400mb的文件时导致Aspnet_wp.exe进程回收而无法成功下载的问题。代码如下&#xff1a;*/Response.ContentType "a…

ITIL管理思想的执行工具发布

E8.HelpDesk是融入ITIL管理思想&#xff0c;并结合中国企业实施ITIL的实际需求&#xff0c;成功研发ITIL管理思想的执行工具&#xff0c;全面帮助中国企业高效导入ITIL管理体系&#xff0c;提升企业战略执行力。 E8.HelpDesk支持多种服务台管理体系&#xff0c;支持事件管理、问…

(C++)A+B 输入输出练习V 输入的第一行是一个正数N,表示后面有N行。每一行的第一个数是M,表示本行后面还有M个数。

#include<cstdio>/* 2 4 1 2 3 4 5 1 2 3 4 5 */int main(){int n,a;scanf("%d",&n);while(n--){int sum 0,m;scanf("%d",&m);for(int i 0;i<m;i){scanf("%d",&a);sum a;}printf("%d\n",sum); }return 0;}

Linux上重启服务的正确命令

在开发环境下&#xff0c;我们经常需要部署代码&#xff0c;重启服务&#xff0c;所以会把命令写在脚本中&#xff0c;方便使用。 我们可能这么写 #!/bin/bashps -ef | grep backend-api-1.0 | grep -v "\-\-color" |awk {print $2} |xargs kill -9 sleep 1 nohup ja…

Error: Most middleware (like bodyParser) ...

运行NodeJS时出现如下错误&#xff1a; Error: Most middleware (like bodyParser) is no longer bundled with Express and must be installed separately. 意思是 命令行中运行 npm install body-parser 回车&#xff0c;进行安装。 对源代码进行调整&#xff0c;加上 var b…

[导入][转]常用CSS缩写语法总结

使用缩写可以帮助减少你CSS文件的大小&#xff0c;更加容易阅读。css缩写的主要规则如下&#xff1a; 颜色 16进制的色彩值&#xff0c;如果每两位的值相同&#xff0c;可以缩写一半&#xff0c;例如&#xff1a; #000000可以缩写为#000;#336699可以缩写为#369; 盒尺寸 通常有下…

(C++)A+B 输入输出练习VI 每行的第一个数N,表示本行后面有N个数。

#include<cstdio>/* 4 1 2 3 4 5 1 2 3 4 5 */int main(){int n;while(scanf("%d",&n) ! EOF){int sum 0,a;for(int i 0;i<n;i){scanf("%d",&a);sum a;}printf("%d\n",sum); }return 0;}

NDK 提示undefined reference to xxx“的解决办法

在Android.mk文件的 LOCAL_SRC_FILES后面加入包含该类或函数的文件&#xff0c;用\隔开&#xff0c;\后换行继续添加 例如 LOCAL_SRC_FILES : NDKTest.cpp\bncore.c\bn_error.c\bn_fast_mp_invmod.c\bn_fast_mp_montgomery_reduce.c\bn_fast_s_mp_mul_digs.c\bn_fast_s_mp_mul_…

7. Query Expressions(查询表达式)

【返回目录】 查询表达式提供了与SQL这样的关系化和分级的查询语言相类似的语言集成的语法。一个查询表达式是以from子句开头以select或者group子句结束&#xff0c;这个初始的from子句可以在其后跟随任意多个from、let、where或者join子句。 那么查询表达式中的这些子句都是做…

CSS完美兼容IE6/IE7/IE8/IE9/IE10的通用方法

300px!important;width /**/:340px;margin:0 10px 0 10px} &#xff0c;关于这个/**/是什么我也不太明白&#xff0c;只知道IE5和firefox都支持但IE6不支持&#xff0c;如果有人理解的话&#xff0c;请告诉我一声&#xff0c;谢了&#xff01;&#xff1a;&#xff09; 3、ul标…

(C++)A+B 输入输出练习VII 输入包含若干行,每行输入两个整数a和b,由空格分隔。 对于每组输入,输出a和b的和,每行输出后接一个空行。

#include<stdio.h> /* 1 5 10 20 */int main() { int a,b;while(scanf("%d%d",&a,&b) ! EOF){printf("%d\n\n",ab);}return 0;}

Address already in use: JVM_Bind错误的解决

错误原因 tomcat的8005端口号被占用了 解决办法 关闭已有的占用端口 1. cmd—>netstat -an 查看当前开启的端口号 2. netstat -ano 获得端口号的pid码 3. skill -{pid} 杀死端口进程转载于:https://www.cnblogs.com/lxq0309/p/3736899.html

在SQL Server中如何转化长日期形式为短日期格式

convert(nvarchar(10),字段名,121)即可将时间格式转化为yyyy-mm-dd格式 convert中的121是指将datetime类型转换为char类型时获得包括世纪位数的4位年份。转载于:https://www.cnblogs.com/footleg/archive/2007/11/29/976451.html

看看Vector源码Java 9

2019独角兽企业重金招聘Python工程师标准>>> Vector类实现了一个可增长的对象数组。像数组一样&#xff0c;它包含可以使用整数索引随机访问。但是&#xff0c;Vector的大小可以根据需要增大或缩小&#xff0c;以适应在创建Vector之后添加和删除项目。 文档里的内容…

(C++)1016 部分A+B 正整数

#include<cstdio>int main(){ //1.读入a,Da,b,Dblong long a,b,Pa0,Pb0;int Da,Db;scanf("%lld%d%lld%d",&a,&Da,&b,&Db); //2.对于a,遍历每一位&#xff0c;加在Pa上 //2.1取余的方式遍历while(a>0){if(a%10Da){Pa Pa*10 Da;}a a/10;} …

MySQL Innodb日志机制深入分析

1.1. Log & Checkpoint Innodb的事务日志是指Redo log&#xff0c;简称Log,保存在日志文件ib_logfile*里面。Innodb还有另外一个日志Undo log&#xff0c;但Undo log是存放在共享表空间里面的&#xff08;ibdata*文件&#xff09;。 由于Log和Checkpoint紧密相关&#xff0…

单元测试的重要性

一些错误的认识 在实际的单元测试过程中总会有一些错误的认识左右着我们&#xff0c;使之成为单元测试最大的障碍&#xff0c;在此将其一一分析如下&#xff1a; 它太浪费时间了&#xff0c;现在要赶进度&#xff0c;时间上根本不允许&#xff0c;或者随便做做应付领导。 我是一…

浅谈网络协议(四) IP的由来--DHCP与PXE

2019独角兽企业重金招聘Python工程师标准>>> 上一节说过&#xff0c;IP就是一台计算机的通讯地址&#xff0c;要和其他机器通讯&#xff0c;就需要一个通讯地址&#xff0c;就要给网卡配置这么一个地址。 配置 IP 那如何配置呢&#xff1f;可以使用 ifconfig&#x…

(C++)1026 程序运行时间

#include<cstdio> const int CLK_TCK100;int main(){ //1.读入c1,c2int c1,c2;scanf("%d%d",&c1,&c2); //2.定义常量CLK_TCK100 //难点&#xff1a;不足 1 秒的时间四舍五入到秒 --不用round()&#xff0c;避免浮点数运算 int dif c2-c1;if(dif%100&…

Spring中@Autowired注解、@Resource注解的区别

Spring不但支持自己定义的Autowired注解&#xff0c;还支持几个由JSR-250规范定义的注解&#xff0c;它们分别是Resource、PostConstruct以及PreDestroy。  Resource的作用相当于Autowired&#xff0c;只不过Autowired按byType自动注入&#xff0c;而Resource默认按 byName自…

(C++)1046 划拳

划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为&#xff1a;每人口中喊出一个数字&#xff0c;同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和&#xff0c;谁就赢了&#xff0c;输家罚一杯酒。两人同赢或两人同输则继续下一轮&…

JAVA中重写equals()方法的同时要重写hashcode()方法

object对象中的 public boolean equals(Object obj)&#xff0c;对于任何非空引用值 x 和 y&#xff0c;当且仅当 x 和 y 引用同一个对象时&#xff0c;此方法才返回 true&#xff1b;注意&#xff1a;当此方法被重写时&#xff0c;通常有必要重写 hashCode 方法&#xff0c;以…

从0到1,苏宁API网关的演进之路

http://www.infoq.com/cn/articles/suning-11-11-api-gateway?utm_campaigninfoq_content&utm_sourceinfoq&utm_mediumfeed&utm_termglobal 2012年&#xff0c;在开放云融推动各产业全面发展的大背景下&#xff0c;苏宁API对外开放。基于苏宁各内部业务系统的资源…

HTML 注意事项

这行与下面图片的间距比较小asdf 代码如下: <table id"table1"cellspacing"0"cellpadding"0"width"100%"border"0"><tbody><tr><td>这行与下面图片的间距比较小</td></tr><tr>&l…

(C++)1008 数组元素循环右移问题

#include<cstdio> //注意&#xff1a;不允许使用另外数组,序列结尾不能有多余空格,不能直接认为right<n //1.读入数组长度&#xff0c;和右移位数&#xff0c;读入数组 //2.未必要对实际数组进行循环右移&#xff0c;只要输出结果表现出那样就可以 int main(){int n…

C# 文件操作(上传 下载 删除 文件列表...)

using System.IO; 1.文件上传 ---------- 如下要点&#xff1a; HTML部分&#xff1a; <form id"form1" runat"server" method"post" enctype"multipart/form-data"> <input id"FileUpLoad" type"file" …