企业集成有很多种模式,随着技术的发展,实时的、面向消息的企业集成越来越成为主流,面向消息的企业集成的稳定性和兼容性要求其基础件,也就是
message
系统必须提供足够强壮和可扩展的设计,下面几种是作为面向消息的企业集成的基础件所必须提供的几个关键性组件。
消息集成使得
message
系统负责转换两个应用之间的数据格式,从而使得应用可以专注于他们需要共享什么数据而不是如何共享它们。
以下这些组件,在著名的ESB系统Mule中都可以见到,有兴趣的同学可以去看看Mule的源代码,虽然Mule对ESB的实现有很多不成熟的地方,以至于让我不敢在生产系统中使用(唉...可恨的Mule),但是毕竟是一个大而全的系统,值得借鉴一下。
Channels
— Messaging
应用通过一个
Message Channel
传送数据,一个
sender
到
receiver
的虚拟管道。一个新安装的消息系统默认不包含任何
channel
;你必须知道你的应用需要怎样通讯,然后才能建立
channel
来完成它。
Messages
— Message
是在
channel
上传输的不可分割的包。因此,为了传输数据,应用必须将数据打包成一个或多个
packets
,将每个
packet
包装成一个
message
,然后将其传输到一个
channel
。同样的,一个
receiver
应用在接受到
message
后必须从
message
中提取出数据才能使用。
Message
系统应该能重复的传输
message
,直到它成功为止。
Pipes and Filters
—
最简单的情况下,
message
系统将一个消息直接从
sender
计算机传送到
receiver
计算机。然而,通常在消息从
sender
中发出后,
receiver
接受到之前,有一些动作需要对
message
执行。举例来说,
message
也许需要验证或者转换。
Pipes and Filters
架构使用
channel
将多个处理步骤连接起来。
Routing
—
在一个大型的、拥有许多不同的应用和
channel
连接的企业应用中,一个
message
可能需要穿过多个
channel
才能到达最终目的地。
Message
的路由如此复杂以至于最初的发送者无法知道那些
channel
能将
message
传送给最终的
receiver
。因此,最初的发送者将
message
发送给一个
Message Router
,一个以
Pipes and Filters
架构中的
filter
形式存在的应用组件。
Router
将决定如何将
message
发送到最终
receiver
或者至少是下一个
Router
。
Transformation
—
不同的应用的数据格式可能不同。为了调节
sender
和
receiver
之间的数据格式不同的问题,
message
必须经过一个中介的
filter
,一个
Message Translator
,它将
message
从一个格式转换成另外一个格式,或转换成一个公共的格式。
Endpoints
—
大多数的应用程序没有内建的能力来同一个
message
系统交互。因此他们必须包含一个中间层,它知道应用系统如何工作,也知道
message
系统如何工作,并桥接两个系统。这个系统是一组并列的
Message Endpoints
,它能够使得应用发送和接受
message
。
System manager
-
作为一个大型的消息集成系统,其面向消息的、异步、低耦合的本质使得系统更加难以调试,运行期的状态也难以跟踪,所以,我们必须有强有力的手段进行系统的运行期管理和监控,同时最好能够在运行进行动态更新,以保障系统的强壮性。
企业应用集成是一个巨大而复杂的系统,作为其基础件 ESB 系统,必须能够提供对其完全的支撑以及足够强壮的系统,这正是 ESB 系统建设的难度所在。
企业应用集成是一个巨大而复杂的系统,作为其基础件 ESB 系统,必须能够提供对其完全的支撑以及足够强壮的系统,这正是 ESB 系统建设的难度所在。
在前面一个专题中,我们列出了一个
ESB
系统所需要关心的所有方面的关键组件,这里介绍其中的
Message Channels
所关注的问题及相关的模式。
Message Channel
主题之下包含以下模式,分别用于解决
channel
中不同方面的问题:
l
Point-to-Point Channel
l
Publish-Subscribe Channel
l
Datatype Channel
l
Invalid Message Channel
l
Dead Letter Channel
l
Guaranteed Delivery
l
Channel Adapter
l
Messaging Bridge
l
Message Bus
当两个应用需要交换数据,它们通过连接两端的
channel
来发送数据。发送的应用可能不知道哪个应用将接受数据。然而,通过选择特定的
channel
来发送,发送者知道接受者将是守候在
channel
另一端等待数据的应用之一。通过这种方式,生产数据的应用有了一个同数据消费者通讯的途径。
Message Channels
面对的各个主要问题:
如果一个应用要传输或接受数据,它一定会用到一个
channel
。问题是你的应用要知道要使用什么样的
channel
,以及用它来做什么。
固定的
channel
集合
-
Channel
中讨论的一个主题是,一个应用可用的
Message Channel
集合一般是固定的。设计一个应用时,一个开发者必须知道将某种类型的数据放到哪里可以同其他应用共享该数据,以及从什么地方可以找到其他应用的特定数据。这些通讯路径不会在运行期动态的创建和发现;它们需要在设计期间就确定下来,以便应用知道它的数据从哪里来以及数据将去哪里。(
虽然大多数
channel
必须被静态定义使正确的,但是也有例外,有些情况下动态
channel
是很好用的。一个例外就是
Request-Reply
模式中的
reply channel
。请求者可以创建或者获得一个应答者不知道的新的
channel
,并在请求消息中指定该
channel
为
Return Address
,应答者就可以使用它。另外一个例外是支持集成
channels
的消息系统实现。一个接受者可以订阅一个集成体系的根
channel
,然后发送者可以发布消息到一个子
channel
,而接受者不需要知道子
channel
,仍然会收到消息。这些都是不常见的情况,
channel
通常仍然是在部署之前被定义,并且应用被设计连接到一个已知的
channel
集合
)。
决定
channel
的集合
-
一个相关的主题是,谁决定那些
Message Channel
是可用的
-
message
系统还是应用程序?换句话说,是由消息系统确定一些
channel
,然后要求应用程序使用它们?还是应用决定它们需要什么
channel
,然后要求消息系统提供它们?这个问题没有一个简单的答案,设计必须的
channel
集合是迭代的。首先,应用要决定消息系统提供哪些
channel
。然后应用将围绕这些
channel
设计它们的通讯,但是如果这样是不可行的,它们将需要添加额外的
channel
。当一些应用已经使用了一个确定的
channel
集合,当加入新的应用,它们将使用已存在的
channel
。当为应用添加新的功能,它们需要新的
channel
。
单向
channel
-
另外一个经常引起混淆的是一个
Message channel
是单向的还是双向的。技术上来说,两者都不是,一个
channel
更像是一个桶,一个应用放入数据,另外一个应用从中取出数据。但是由于数据是放在消息中从一个应用传到另一个,这使得
channel
具有方向性,使它变成单向的。如果一个
channel
是双向的,应用将从中发送和接受数据,虽然技术上是可行的,但是会有小小的问题,应用将有可能持续的取出自己放进去的希望发送给其他应用的消息。所以,为了实践性的目的,
channel
是单向的。作为结论,两个应用如果有双向通讯,它们需要两个
channel
,每个方向一个
。
如何使用
Message channels
:
现在我们来讨论以下如何使用
channel
。
一对一或者一对多
-
当你的应用共享一些数据,你希望只将它共享给一个应用还是对它感兴趣的所有应用?要传送数据到一个单独的应用,使用
Point-to-Point Channel
。这并不意味着发送到这个
channel
的每个数据都发送给同样的接受者,因为一个
channel
可能有多个接受者。它意味着,实际上,保证每个数据都被同一个应用接收。如果你想让所有接收应用都能接收数据,使用
Publish-Subscribe Channel
。当你通过这种方式发送数据,
channel
将高效的复制数据到每一个接收者。
什么类型的数据
-
任何内存中的数据都有一个类型。另一方面,所有数据都是一些
bytes
集合。消息系统工作同这类似,消息内容必须符合某些类型以便接受者了解数据的结构。
Datatype Channel
认为在一个
channel
中的数据必须拥有同样的类型。这也是为什么消息系统需要很多
channel
的主要原因
(每个
channel
一种格式)。如果数据可以是任意的格式,那么消息系统在两个应用之间只需要两条
channel
。
无效的和过期的消息
-
消息系统可以确定消息被正确的传输,但是它不能保证接受者知道如何处理它。接收者对数据格式和意义存在期望。当它接收到一个不符合期望的消息,它什么也不能做。它们能作的,就是将这个陌生的消息放入到一个特别设计的
Invalid Message Channel
并希望某些监控这个
channel
的工具能够取出这个消息,并指出该如何处置它们。许多消息系统有一个类似的内建特征,一个
Dead Letter Channel
,用来存放成功送出但却无法成功投递的消息。另外,一个系统管理工具应该监视
Dead Letter Channel
并且决定如何处置这些无法投递的消息。
故障检测
-
如果一个消息系统发生故障或停机维护,它的消息会怎样?当它重启并重新运行,它的消息能否还在它的
channel
中?默认的:不会;
channel
将消息存储在内存中。然而,
Guaranteed Delivery
将
channel
持久化以便将它们的消息存储到硬盘上。这会影响效率,但会使消息更加可靠,即使消息系统是不可靠的。
非消息客户端
-
如果一个应用不能连接到一个消息系统但是仍然想要参与消息怎么办?通常它只能自认倒霉了,但是如果消息系统可以通过某种方式连接到应用系统
-
通过它的用户界面,它的
service API
,它的数据库,或者一个
TCP/IP
或
HTTP
这样的网络连接
-
那么消息系统可以使用一个
Channel Adapter
。这允许你连接到一个或多个连接到应用的
channel
而不必改变应用或者可能也不需要一个同应用运行在同一个机器上的消息客户端。有时‘非消息客户端’真的是一个消息客户端,但是只有连接的是其他消息系统的时候。
通讯中枢
-
随着越来越多的企业应用系统连接到消息系统以便通过消息暴露他们的功能,消息系统变成了企业中一站式功能的集散地。一个应用只需简单的知道用哪个
channel
来请求功能,以及从哪个监听结果。消息系统本质上变成一个消息总线,一个提供所有企业应用甚至变化中的应用和功能的中枢。你可以更快速的集成。
如你所见,使用消息构建应用不仅仅是将他们连接到消息系统并发送消息。消息必须使用
Message Channel
来发送。
Channel
必须被设计为某个目的服务,比如基于被共享的数据类型,共享数据的应用类型,和接收数据的应用。
3
在前面的
关键组件
中我们提到了
Messages
。当两个应用想要交换数据,他们将数据包装在一个
message
中。但是一个
Message Channel
不能传输原始数据,它只能传输包含在一个
message
中的数据(即传输特定格式的数据)。
Message
在消息系统中处于信息载体的位置,而在
ESB
中,还消息识别、序列以及生存周期等职责。
Message
的结构涉及以下几个模式:
l
Command Message
l
Document Message
l
Event Message
l
Request-Reply
l
Return Address
l
Correlation Identifier
l
Message Sequence
l
Message Expiration
l
Format Indicator
创建和发送一个
Message
产生以下几个问题:
消息意图
-
Message
最终是为了运送一些数据,但是发送者可能有其他目的,比如它希望接受者使用消息做些事情。它可以发送一个
Command Message
,指定它希望调用的接受者上的函数或方法。发送者告诉接受者运行那些代码。发送者可以发送一个
Document Message
来传送它的数据结构到接受者。发送者发送数据到接受者,但是不指定接受者应该做什么。
或者它可以发送一个
Event Message
,通知接受者发送者那里有一个改变。发送者不应告诉接受者应该怎样适应这个改变,而只应提供通知。
返回一个应答
-
当一个应用发送一个消息,它通常期望得到一个回应来确定消息被处理并提供一个结果。这是一个
Request-Reply
场景。
Request
通常是一个
Command Message
,而应答是一个包含返回值或异常的
Document Message
。请求者应该在请求中指定一个
Return Address
来告诉应答者使用哪个通道来传回应答。请求者可能在一个处理过程中发送多个请求,所以应答应该包含一个
Correlation Identifier
来指出这个应答对应哪个请求。
有两个
Request-Reply
场景需要注意;它们都包含了一个
Command Message
请求和一个对应的
Document Message
应答。在第一个场景中,
Message RPC
,请求不但要调用应答者的函数,而且期望一个返回值。这是
RPC
。另一个场景中,
Message Query
,请求者执行一个查询;应答者执行查询并在应答中返回结果。这是远程查询。
大量的数据
-
有时应用想要传送大量的数据结构,放入一个单独的
message
里面不是很合适。在这种情况下,将他们分解成可管理的消息块并将他们作为
Message Sequence
发送。这些消息必须按顺序发送,以便接受者能够充足原始数据结构。
慢速消息
-
消息系统的一个问题是发送者通常不知道接受者要多久才能接受到消息。然而,消息的内容可能是时间敏感的,所以如果消息在某一时间内没有被接受,它将被忽略并取消。在这种情况下,
sender
应该使用
Message Expiration
来指定一个到期时间。如果消息系统在规定时间内无法传输一个消息,应该将它取消并删除到
Dead Letter Channel
中。同样的一个
receiver
接受到一个超出该时间点的消息,也要取消该消息。
总之,只选择使用消息是不够的。使一个消息工作的其他决定性因素来自于消息所要完成的任务。
![](https://p-blog.csdn.net/images/p_blog_csdn_net/superpan/941f8be019d344188139321dd55b5a89.jpg)
评论
当两个应用想要交换数据,他们将数据包装在一个
message
中。但是一个
Message Channel
不能传输原始数据,它只能传输包含在一个
message
中的数据(即传输特定格式的数据)。
fisher on csdn 引用了该文章 , 地址 :http://blog.csdn.net/flyingbug/archive/2005/11/19/533102.aspx
fisher on csdn 引用了该文章 , 地址 :http://blog.csdn.net/flyingbug/archive/2005/11/19/533102.aspx
2005-11-19 20:39 | fisher on csdn
好文
,
我也正想研究
EAI
平台
,
其中
ESB
则是
EAI
平台的核心
,
期待你的后文
,
另 : 能否多讲一些有关 IBM MQ 的消息中间件 , 在大型企业应用中 , 往往都采用的是 MQ 渠道 , 毕境简单的基于 SOAP 连接的 WEB SERVICE 拥有先天缺陷 --- 无法共享连接 .
另 : 能否多讲一些有关 IBM MQ 的消息中间件 , 在大型企业应用中 , 往往都采用的是 MQ 渠道 , 毕境简单的基于 SOAP 连接的 WEB SERVICE 拥有先天缺陷 --- 无法共享连接 .
2005-11-21 11:23 | langds
呵呵,没用过
MQ
,所以没办法写关于
MQ
的内容了
我想 SOAP 的好处是基于 XML 的标准提供了互通的平台,并且它在消息转换、元数据交换以及安全方面都提供了标准的做法,我认为 SOAP 是一个很有前途的集成手段
SOAP 的缺陷是由 Http 协议的基于请求的、无状态的特性决定的,这也没办法
但是可以通过一些设计模式来适当的改变这种状态,比如使用 Cache
或硬性的保持一个通知连接等机制
我想 SOAP 的好处是基于 XML 的标准提供了互通的平台,并且它在消息转换、元数据交换以及安全方面都提供了标准的做法,我认为 SOAP 是一个很有前途的集成手段
SOAP 的缺陷是由 Http 协议的基于请求的、无状态的特性决定的,这也没办法
但是可以通过一些设计模式来适当的改变这种状态,比如使用 Cache
或硬性的保持一个通知连接等机制
2005-11-21 21:55 | fisher
是的
,
不论怎么样
,
在
SOA
应用架构下
,
基于
SOAP
协议的交互的确是相当重要的
,
因此才出现了面向消息的
SOA
实现
,
这就会在
ESB
里的消息通迅模式里解决
.
而
IBM
的
MQ
则是比较好的方案了
2005-11-22 10:04 | langds
呵呵,我个人感觉
Message Queue
并非什么神奇的技术,而且也不是普遍适用的技术
其实真正通用的整合标准就只有两个: Http 和 Socket
SOAP 是 Http 上的技术, Socket 则是十年前的整合标准
无论使用哪一种都一样
基于 Socket 的整合的中间件我都是自己写的,所以我没有用过 MQ
只要通讯基础框架写的好,支持什么样协议我想都不是大问题 ^_^
其实真正通用的整合标准就只有两个: Http 和 Socket
SOAP 是 Http 上的技术, Socket 则是十年前的整合标准
无论使用哪一种都一样
基于 Socket 的整合的中间件我都是自己写的,所以我没有用过 MQ
只要通讯基础框架写的好,支持什么样协议我想都不是大问题 ^_^
4
通常,通过消息系统集成的应用很少有同样的消息格式。比如说,一个帐务系统同一个
CRM
系统对客户对象是有着不同的概念的。基于这个,一个系统可能将消息存储在关系表中,另一个可能存储在文件中。集成已存在的系统通常意味着我们没有修改系统以便使他们更好的一起工作的自由。然而,集成方案不得不协调和解决各种系统之间的不同。
Message Translator
模式提供了一个通用的解决方案。这里解释几种特定的
Message Translator
。
Message Transformation
包含以下几种模式:
l
Envelope Wrapper
l
Content Enricher
l
Content Filter
l
Claim Check
l
Normalizer
l
Canonical Data Model
大多数消息系统放置特定的需求在消息头的格式和内容中。我们包装有效数据到一个
Envelope Wrapper
中以适应消息基础设施的需求。如果消息需要穿过不同的消息基础设施,可以结合多个
Envelope Wrapper
。
如果原始系统不能提供目标系统需要的数据域,可以使用一个
Content Enricher
。它可以查找缺少的信息并从已有数据中计算出它。
Content Filter
正好相反,它从消息中删除不需要的数据。
Claim Check
也从消息中删除数据,但是它将存储他们以便以后取回。
Normalizer
将多个不同格式的消息翻译成统一格式。
消除依赖
消息转换在集成中是一个很深的话题。
Message Channels
和
Message Routers
可以通过消除应用必须知道另外一个应用的位置的需求从而解除应用间的基本依赖。
一个应用可以发送一个消息到
Message Channel
而不必担心谁来取出消息。然而消息格式增加了另外一种依赖。如果一个应用不得不将消息格式化成另外一个应用的数据格式,通过
Message Channel
解耦的说法就像一个幻想。接收系统的任何改变或切换到另外一个接收系统都需要对发送应用进行改变。
Message Translators
可以帮助除去这种依赖。
元数据管理
将消息从一个消息格式转换到另一个格式需要操作元数据
-
描述数据格式的数据。
元数据在两个并行系统之间的集成中扮演着非常重要的角色。一个处理实际的消息数据,另外一个处理元数据。许多用于处理消息数据的模式也同样可以管理元数据。比如说,
Channel Adapter
不仅可以从一个系统中移进和移出消息,还可以从一个外部应用中获取元数据,并将其加载到一个元数据仓库中。使用这个仓库,集成开发者可以定义应用元数据与
Canonical Data Model.
之间的转换。
元数据集成
![](https://p-blog.csdn.net/images/p_blog_csdn_net/superpan/d29635bb7413479b8dc017894ba52354.jpg)
举例来说,上面的图描述了两个需要交换客户信息的应用的集成。每个系统的客户数据的定义稍有不同。从 A 到 B 的消息需要转换一下才能被 B 接收。如果 Channel Adapters 可以抽取元数据的话,创建一个转换将非常简单。然后这个元数据可以被放入一个仓库,大大的简化了 Message Translator 的配置和验证。元数据可以被存储成不同的格式。通常 XML 消息使用 XSD 格式。其他 EAI 工具实现所有元数据格式,但是允许管理员导入或导出到其他格式。
消息系统外的数据转换
这些转换模式组成的很多原则可以被应用于非消息集成。比如说,
File Transfer
可以执行系统间的转换工作。类似的,
Remote Procedure Invocation
必须使请求使用要调用的
service
的格式,即使应用本身的格式可能不同。典型的,需要调用程序来执行转换。一些最成熟的转换引擎组成了
ETL
工具,比如
Informatica
或者
DataMirror
。这些工具一般都一次转换大量的数据,而不是转换单个消息。
Message System
应专注于几种基本的
Message Translator
模式。而不应该关心实体间结构转换的细节(不同的数据模型之间的转换,比如
ER
模型不支持多对多关系而其他的支持这种)。关于这个主题最老也使最相关的书是
Kent
的《
Data and Reality
》。
![](https://p-blog.csdn.net/images/p_blog_csdn_net/superpan/603bdc6e8af146f493bf25b271a7f439.jpg)
评论
通常,通过消息系统集成的应用很少有同样的消息格式。比如说,一个帐务系统同一个
CRM
系统对客户对象是有着不同的概念的。基于这个,一个系统可能将消息存储在关系表中,另一个可能存储在文件中。集成已存在的系统通常意味着我们没有修改系统以便使他们更好的一起工作的自由。然而,集成方案不得不协调和解决各种系统之间的不同。
fisher on csdn 引用了该文章 , 地址 :http://blog.csdn.net/flyingbug/archive/2005/11/21/534215.aspx
fisher on csdn 引用了该文章 , 地址 :http://blog.csdn.net/flyingbug/archive/2005/11/21/534215.aspx
2005-11-21 22:10 | fisher on csdn
5
在 ESB 中另外一个重要的课题就是 Message Endpoint ,这是关于一个应用程序如何连接到一个消息系统,并通过它来发送和接收消息。如果你在面向一个消息 API 编程,则你就正在开发一个 endpoint 代码。商业中间件通常都提供了这些工具。
l
Messaging Gateway
l
Messaging Mapper
l
Transactional Client
l
Polling Consumer
l
Event-Driven Consumer
l
Competing Consumers
l
Message Dispatcher
l
Selective Consumer
l
Durable Subscriber
l
Idempotent Receiver
l
Service Activator
发送和接收模式
有些
endpoint
模式既可以使用在发送方也可以使用在接受方。它们描述一个应用连接一个消息系统的一般情况。
包装消息代码
-
一个应用不应该意识到正在使用消息同另外一个应用程序通讯,大多数应用代码应该在不知道
message
的情况下被编写。在应用集成的地方,应该有一个薄薄的一层代码来执行应用的集成部分。当集成是由消息实现的,这层将应用连接到消息系统的代码称为一个
Message Gateway
数据转换
-
当发送者和接受者使用不同的数据格式,或者不同的消息格式(支持不同的发送和接收者),在这种情况下,使用一个
Message Mapper
来在应用格式和消息格式之间转换数据。
外部控制的事务
-
消息系统在内部和外部使用事务,默认的,每个发送和接收方法在他们自己的事务中运行。
Message
生产者和消费者应可选的使用一个
Transactional Client
来控制事务,当你需要将几个消息一起发送伙通过其他事务服务整理消息时是很有用的。
消息消费者模式
其他
endpoint
模式只适用于消息消费者,发送消息是简单的。棘手的问题是决定一个消息应该何时发送,它应包含什么,以及怎样将它送到接受者
-
这是为什么我们有很多消息结构模式
-
但是一旦消息被构建,发送它是很容易的。另一方面,接收消息
-
很麻烦。因此许多
endpoint
模式是关于接收消息的。
接收消息的一个最重要的主题就是流量控制:一个应用控制,或者调节它消费消息的速度。一个潜在的问题是任何
server
都面临着大量的客户端请求会使其超载。通过远程过程调用(
RPI
),
server
几乎受到客户端调用的支配。同样的,通过消息,
server
不能控制客户端发送请求的速度
-
但是
server
可是控制它处理这些请求的速度。应用不必像消息系统传送消息那么快的接收并处理消息;使用一个
Message Channel
可以使它在一个可接收的速率上处理消息。然而,当消息积累太多,而
server
还有资源可以处理的更快,它可以使用同步
message
消费者来加快速度。所以使用这些消息消费者模式可以让你的应用将速度控制在它可以承受的范围。
许多消息消费者模式都是成对出现的,你可以任选一个使用。
同步或异步接受者
-
可以使用轮询消费者或一个事件驱动消费者。轮询提供最好的流量控制,因为如果
server
忙,则它不再继续轮询消息,所以
message
将阻塞在队列。事件驱动的消费者倾向于消息到达便触发处理,所以有可能会使
server
超载,但是每个消费者每次只处理一个消息,所以限制消费者的数量可以有效的控制消费速度。
消息分派
vs
消息获取
-
另外一个二选一的模式是一堆消费者如何处理一堆消息。如果每个消费者获得一个消息,他们可以并行的处理消息。最简单的方法是
Competing Consumers
,也就是一个点对点的
channel
有多个消费者。每个都可能获得任何消息;消息系统的实现决定那个消费者获得消息。如果你想控制消息到消费者的匹配过程,使用
Message Dispatcher
。
这时只有一个消费者接收消息,但是将委派消息到一个执行者去处理。一个应用程序可以通过限制消费者或执行者的数量来控制流量。当然,分派者
Message Dispatcher
也可以实现一个流量控制行为。
接收所有消息或者过滤
-
默认的,任何到达一个
Message Channel
的消息对于监听着这个
channel
的
Message Endpoint
都是可用的。然而有些消费者并不打算处理
channel
上的任何消息,而是希望只处理其中几种。这样一个识别的消费者可以使用一个
Selective Consumer
来描述它将接收什么类型的消息。然后消息系统将只将匹配的消息对该接受者描述为可用。
当断开连接的时候订阅消息
-
Publish-Subscribe Channels
带来的问题是,如果一个消费者感兴趣一个
channel
,但是现在网络是断开的怎么办?是不是一个未连接的应用将错过发布的消息,即使它已经订阅过该消息
?
默认的,是的,订阅只对连接的订阅者有效,为了使应用不会因为连接而错过订阅的消息,要使用
Durable Subscriber
。
等幂
-
有时一个消息可能被传输不只一次,可能因为消息系统不确定该消息是否已经被成功的传递过,或者可能因为
Message Channel
的
QoS
被设置较低来提高效率。另一面的,消息接受者认为每个消息只会被传输一次,并且当它们重复处理相同的消息,它们会出错。一个
Idempotent Receiver
可以优雅的处理重复的消息,并且阻止它们引起接收者应用的发生错误。
同步或异步服务
-
另外一个选择是一个应用应该暴露它的
service
为同步(
RPI
)还是异步的(
Messaging
)。不同的客户端可能喜欢不同的方式;不同的环境可能需要不同的方式。既然很难选择,就一起使用。一个
Service Activator
连接一个
Message Channel
到一个应用的同步服务以便当一个消息被接收,
service
就被调用。同步客户端可以简单的直接调用
service
;异步客户端可以通过发送消息调用
service
。
Message Endpoint
的相关主题
Message Endpoint
的另外一个重要主题是很难同其他模式共同应用
Transactional Client
。
Event-Driven Consumer
通常不能适当的在外部控制事务,
Message Dispatcher
也必须小心的设计这个问题,
Competing Consumers
的事务也是个重大问题。最安全的使用
Transactional Client
是使用一个单独的
Polling Consumer
,但是这不会是一个令人满意的解决方案。
这里特别要提到应该会保证成功的
JMS
风格的
MDB
,
EJB
的一种。一个
MDB
是一个消息消费者,它即使一个
Event-Driven Consumer
又是一个支持
J2EE
分布式事务的
Transactional Client
,并且它可以作为
Competing Consumers
动态的池化,甚至作为一个
Publish-Subscribe Channel
。这是在一个自由的应用中实现这些是一个困难且乏味的组合,但是这个功能作为一个
EJB
容器的内建的功能被提供。(
MDB
框架如何实现的?本质上,容器通过一个动态改变大小的可重用的执行者的线程池来实现了一个
Message Dispatcher
,在那里每个执行者自己使用自己的
session
和事务来消费消息。)
最后,紧记一个单独的
Message Endpoint
可以很好结合几个不同的模式。一组
Competing Consumers
可以被作为
Polling Consumers
实现,同时也可以是一个
Selective Consumers
并且可以作为一个
Service Activator
调用一个应用的
service
。
一个
Message Dispatcher
可以是一个
Event-Driven Consumer
和一个使用
Messaging Mapper
的一个
Durable Subscriber
。无论一个
endpoint
实现什么模式,它总是一个
Messaging Gateway
。所以,不要考虑使用哪种模式
-
而要考虑如何结合他们。这是使用模式解决问题的魅力所在。
要实现一个
Message Endpoint
有很多选择。
Message Endpoint
模式用于解释这些选择是什么以及如何最好的使用它们。
6
开发一个基于消息的解决方案是不容易的事情,在生产中操作这样一个产品同样也是一个挑战:一个基于消息的集成解决方案一天可以产生、路由和转换成千上万的消息。我们不得不处理异常、效率瓶颈或改变合作系统。而为了使事情变得更加有挑战性,组件经常被分布在不同的平台和机器上,甚至位于不同的地理位置。
System Management
包含以下几种模式
l
Control Bus
l
Detour
l
Wire Tap
l
Message History
l
Message Store
l
Smart Proxy
l
Test Message
l
Channel Purger
除了与生据来的复杂性、分布式集成的规模以及个性化的应用之外,低耦合的架构使得测试和
debug
变得更加困难。
Martin Fowler
将这个症状称为“架构师的梦想,开发者的梦魇”。低耦合的架构原则以及间接的依赖于外部系统提供了灵活性。然而,测试一个消息生产者不了解消息消费者的系统可能会是一个挑战。另外异步的和时间相关的消息使得事情变的更加复杂。举例来说,消息方案可能被设计没有被成消息生产者者必须从接受者那里得到一个回应。同样的消息基础设施通常保证传输消息,但不能保证传输时间。这是的开发基于消息传送结果的测试用例变得困难。
当监控一个消息解决方案,我们可以在两个抽象层面上跟踪消息流。一个典型的系统管理方案监控多少消息被发送或者它多长时间得到一个被处理的消息。这些监控方案不检查消息数据,除了可能会检查消息头中的几个字段(比如消息标识或者消息历史)。与之相对的,
BAM
(
business activity monitoring
)方案聚焦于包含在消息中的有效数据,举例来说,发生在过去一小时的所有订单的金额。
System Management
中的很多模式都足够通用并可以用在以上两个目的中(监控消息头或者消息内容)。然而,由于
BAM
本身就是一个新领域,并且需要从数据仓库中获得很多数据(有些我们根本就没有涉及到),我们决定在系统管理的内容中讨论这些模式。
系统管理模式被设计用于为保持一个基于消息的复杂系统的运转所提出的需求并提供工具。
System Management
的模式涉及三个种类:监控和控制,观察和分析消息流量,测试和调试。
监控和控制
一个
Control Bus
提供一个单独的控制点来对一个分布式方案进行监控和管理。它将多个组件连接到一个中心管理控制台,这里可以显示每个组件的状态并且监控通过每个组件的消息流量。控制台同时也可以用于发送控制命令给组件,比如,转变消息流。
我们可能想要在路由消息时添加附加的步骤,比如验证或者日志。由于这些步骤可能使效率降低,所以我们可以通过
Control Bus
来控制他们开关。一个
Detour
为我们提供这种能力。
观察和分析消息流量
有时我们想要在不影响主要消息流的情况下观察消息的内容。一个
Wire Tap
允许我们接入到消息流中。
当我们调试一个基于消息的系统,知道一个特定的消息在哪使很有帮助的。
Message History
保留一个消息访问过的所有组件的日志,而不需要增加组件间的依赖。
然而
Message History
依赖于单独的消息,一个中心的
Message Store
可以提供一个穿越系统的每个消息的完整记录。结合
Message History
,
Message Store
可以分析所有消息穿过系统的可能路径。
Wire Tap,
Message History,
和
Message Store
帮助我们分析异步的消息流。为了跟踪发送到请求
-
应答
service
的消息,我们需要在消息流中插入一个
Smart Proxy
。
测试和调试
在部署前测试一个消息系统是一个非常好的注意。但是测试不应该停止在部署前。你应该有能力验证正在运行的消息系统运行持续的运行正常。你可以周期性的发送一个
Test Message
到系统中并验证结果。
当一个组件失败或者运行不正常,它可以简单的终止,并放弃一个
channel
中的剩余消息。在测试期间这是很有用的。一个
Channel Purger
可以为我们做这些。