场景概述:
有时需要将多个应用程序集成到一个框架中,这些应用程序常见的基础通信方式包含总线模式、代理模式、
或者点对点模式。一些应用程序发送多种类型的消息,其他应用程序可能更关注这些消息类型的组合。
例如,在一个金融系统存在多个应用程序管理同一客户信息的情况,存在一个客户关系管理程序(CRM)掌握客户信息。
一种典型的情况:客户信息存在于其他系统中,且这些系统执行各自客户信息管理函数来处理客户信息。
当某个面向客户的应用程序生成更新客户信息的消息,例如客户地址的修改时,CRM和其他管理客户信息的程序
都将到该消息,然而,这个消息类型对于那些不管理客户信息的其他程序是没有意义的。
问题:
如何才能让一个程序在集成环境中只发送消息到那些对该消息感兴趣的应用程序中,而不需要知道消息接收方
的基本信息?
约束:
为确保集成的软件能够只接收到各软件感兴趣的消息,这些软件需要满足下列约束条件:
1. 集成框架中的应用程序关注不同的消息类型。例如,管理客户信息的应用程序关注客户信息的更新,贸易程序关注买卖事务,用于双向提交事务消息的应用关注消息的提交。
2. 集成框架中的某个应用可能发送若干个消息类型。例如,应用程序可能发送用户和操作的状态信息。
同样,集成框架中的某个应用通常关注的是其他应用程序发布的消息子集。例如,投资经理只关注那些影响其
所管理的股票的金融信息事务。
3. 应用程序添加不同信息到消息的情况是多种多样的,这种情况下,固定长度的二进制消息通常是不灵活
的,相比而言,使用封装元素来扩展SOAP(简单对象访问协议)消息更为简单。
4. 大多数集成框架集成所有的应用,这些应用通常假定在该集成环境中存在同其他应用通信的消息,甚至
对于一个灵活的消息格式,插入或处理应用未知的消息元素都可能遇到困难。
解决方案:
通过创建主题或动态检测消息内容来扩展通信基础框架。通信框架能确保应用程序能够收到订阅的消息,
并能够创建一种机制来发送消息到所有关注该消息的接收端(订阅方)。
这里列举了三类创建订阅/发布机制方式:
1. List-Based Publish/Subscribe(基于列表的订阅发布模式)
2. Broadcast-Based Publish/Subscribe (基于广播的订阅发布模式)
3. Content-Based Publish/Subscribe (基于内容的订阅发布模式)
这三类模式都能够发送消息到所有关注该消息的订阅方。
List-Based Publish/Subscribe (基于列表的订阅发布模式)
基于列表的订阅发布模式需要管理由订阅方组成的链表,这些订阅方都关注于某一主题。当事件发生时,
订阅方链表上的所有关注该主题的订阅者都将被通知到,这很像常见的观察者模式。当你使用观察者模式时,
需先确定两个类:主题和观察者。假定采用push模式来更新,对于主题(subject)类需要添加三个方法:Attach(), Detach()和Notify(),对于观察者添加Update()方法。
使用观察者模式时,所有观察者以及其所关注的主题将被注册(使用Attach()方法)。当该主题内容发生
改变时,每个关注该主题的观察者都将被通知到。
当你创建对象实例并且具体化所有观察者和主题时,使用观察者模式构建订阅发布比较合适, 观察者和主题
的关系要一直保持。通过构建关系数据库,在多对多的情境下,构建主题与观察者的依赖关系。使用时,通过
检索该关系数据库表,即可获取关注某一主题的所有订阅者。
维护主题和订阅者链表,然后在事件来临时,通知每一个订阅者是基于链表订阅发布实现的基础。
Broadcast-Based Publish/Subscribe(基于广播的订阅发布模式)
当使用基于广播的订阅发布模式时,事件发布方将创建消息并广播到局域网中,每个监听节点都会检查
消息主题,如果主题为该节点所关注的就会接收并处理该消息。如果该主题不是监听节点关注的,就会忽略该
消息。
通常主题可以分层并且可能包含多个域,每个域根据周期来分隔,如果需要监听节点可以采用通配符来订阅
某一特殊主题。
基于广播的订阅发布能够有效的将生产者和消费者解耦,在某些情况,还可以做到区分特殊主题订阅者。
为了区分主题订阅者,协调程序发出消息,订阅该消息的节点将被要求回复,这些响应回复会指明所有该主题
的订阅者。
这种订阅发布体现在所有的消息都会发布到所有的监听节点,每个节点负责过滤不感兴趣的消息。
Content-Based Publish/Subscribe(基于文本内容的订阅发布模式)
基于广播和列表的订阅发布基本上都根据主题来分类,都使用预定义主题的方式实现多对多通信。
基于主题和基于内容通信的不同点如下:
在基于主题的系统,进程交换信息通过一个预订的主题集合,这些主题在多对多的情景下用来区分各
逻辑通道。基于内容的系统更为灵活,因为订阅方与特殊消息内容有关,信息组合的方式被视为动态的
逻辑通道,这极大的扩展了潜在的逻辑通道数量,也改变了订阅发布系统实现的方式。
使用订阅发布
图一显示四个应用程序集成的一种方案。发送方使用基于主题的方式来发布消息给主题A和主题B。其中
三个接收方订阅这些主题;其中一个订阅了主题A,一个订阅了主题B,一个订阅了主题A和B。箭头描述消息发送
路径。
实现订阅发布过程,通常影响消息结构,应用集成和通信基础框架。
首先, 必须区分主题或应用程序感兴趣的内容。这将转化为将消息类型分为不同的子集。例如在贸易领域
消息类型,一些贸易应用需要追踪买入事务,一些追踪卖出事务,其他应用追踪买卖事务。通过创建买入和卖出
主题来分离消息,并将贸易消息划分到不同子集。
下一步,必须给消息中添加信息,这些消息指明主题或识别特殊内容信息。有时可以通过保存主题相关的
信息到消息结构的某个未使用的域内。还有一种方式,可以为主题添加一个新的域,例如在SOAP头中添加一个
新的元素。如果既不能使用已存在的域又不能添加,只能找到某种方式将主题嵌入到消息中,或者使用基于
内容的订阅发布方式。
接下来必须扩展通信基础框架以便消息能够传递给每个订阅者。使用的方法依赖于集成解决方案的拓扑
结构,例如三类普遍的拓扑结构。对于总线结构,可以采用在总线接口上实现订阅机制;对于代理结构,可以
通过为代理者创建订阅者链表来实现;对于点对点结构,可以在发布方创建订阅链表来实现。
最后,需要修改应用集成框架,发布方必须将与主题相关的信息添加到每个发布的消息中。例如,如果主题
作为头元素编入,发布方必须将主题相关信息插入到合适的位置,同样地,订阅方必须明确感兴趣的主题。
订阅方可以是固定或动态的,当订阅方是固定的,集成框架设置应用订阅的主题,应用程序无法控制订阅。
通常,订阅过程由每个应用程序在被添加到集成环境时确定。图二显示一个针对主题A的固定订阅方式。
与之相比,动态订阅能让每个应用程序通过一组控制消息来控制其自身订阅过程。应用程序通过发送消息
到通信基础框架,使其将应用程序从订阅链表中移除,来实现移除订阅内容。大多数提供订阅发布功能的通信
框架都提供该功能,然而,不是非得要动态订阅才能实现这种功能。
上图描述了动态订阅的功能,首先是初始订阅主题A,然后应用发送消息了从订阅链表中移除订阅,接着应用
发送两个消息来订阅主题B和主题C。
相关决定:
在决定使用订阅发布模式后,需要确定下述要素:
1. 初始订阅。 必须确定订阅方首次添加到集成环境中如何通过通信框架与订阅内容通信。
2. 通配符订阅。必须确定是否让订阅发布模式支持通配符订阅。通配符订阅确保订阅者通过一个订阅过程来
订阅多个主题。
3. 静态或动态订阅。必须确定集成解决方案是动态订阅还是静态订阅。
4. 主题发现。 必须确定订阅者在解决方案中支持动态订阅的情况下能够发现可以主题。
职责与协作:
下表为订阅发布个组件的职责和功能。