在前面一个专题中,我们列出了一个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必须被设计为某个目的服务,比如基于被共享的数据类型,共享数据的应用类型,和接收数据的应用。