基于CORBA的可靠消息传递技术
摘要:本文详细的讨论了CORBA(Common Object Request Broker)通知服务对可靠事件传递的支持,实现了基于通知服务尽可能可靠的事件传递,提出了一个用CORBA通知服务实现可靠事件传递的框架。
关键字:CORBA, 通知服务,可靠消息
Reliable Message Transfer Based on CORBA
Zhou Shunli, Xue He, Xu Wangshan
(Department of Northwest Polytechnical University,Xi’an,710072)
Abstract: This paper discussed the support for reliable message of the CORBA Notification Service, proposed a reliable message transfer framework based on Notification Service that can provide the most reliable event delivery possible with the CORBA Notification Service.
Keywords: CORBA, Notification Service,Reliable Message
一 引言
基于CORBA的分布是架构逐渐成为分布是计算基础设施的基础。由OMG制定的 CORBA事件服务标准实现了消息的发布和订阅,事件服务定义的事件可能是一个机票预定系统的机票价格的变动或者是一个监控系统中的报警或者故障信息,但是事件服务的说明书中并没有对可靠性做任何规定。
下一代的通信软件和分布式服务要求具有高可靠性,高可用性,可扩展性和灵活性。一种可靠的CORBA消息传递解决方案成为值得研究的问题。事件服务作为最初的解决方案,没有提供足够的可靠性支持,缺少如可配置的服务质量和过滤机制。通知服务正是为了解决这些问题而提出来的,它对事件服务进行了功能性的扩展,增加了定义良好的结构化的事件,可配置的QoS(服务质量)和功能强大的事件过滤机制。并且保留了所有事件服务的语义,可以实现和原有的事件服务的客户端的互操作。本文介绍了通知服务,对通知服务的事件传递语义和QoS特性进行了分析和总结,在它的基础上设计了一个可靠的事件传递框架。
二 CORBA通知服务
2.1 通知服务的架构
通知服务是为了解决事件服务的事件和连接缺乏持久性,事件过滤,QoS和管理机制。通知服务同时扩展了事件服务,提供了一个新的结构化的事件,允许事件提供者和事件供应者相互发现事件类型。下边我们来讨论通知服务提供的可靠事件传递的机制。通知服务Push模式的逻辑视图如下:
图1 通知服务逻辑视图
首先是创建带有QoS和管理机制事件通道,下来创建的对象都继承了事件通道的QoS和管理特性。事件通道被创建后,自动创建相应的SupplierAdmin和ConsumerAdmin接口。一个供应者如果要向消费者传递事件,首先需要通过消费者Admin接口得到一个消费者代理,然后连接这个代理。同样一个消费者如果需要向供应者传递事件,首先需要通过SupplierAdmin接口得到一个供应者代理,然后连接这个代理。代理实现了供应者和消费者的解耦。每一个事件通道都有一个Master queue用来缓冲进入该事件通道的事件。每一个供应者代理都维持一个队列用来缓存所有连接到它上边的消费者的事件。每一个Admins和代理还可以有一些过滤条件来决定一个事件是被继续传递还是被丢弃。ConsumerAdins同样可以通过“maping filters”来改变事件的优先级和生命周期等QoS特性。
对于Pull模式来说,供应者和消费者分别从事件通道里边Pull事件。QoS和管理特性等的处理和push模式是一致的。Push和Pull可以混合使用。一个供应者可能向事件通道里边Push事件,然后消费者从事件通道里边Pull事件。
当供应者和消费者通过事件通道连接在一起的时候,事件在传递的过程中存在三个阶段:供应者和事件通道之间,事件通道中和事件通道和消费者之间。在这样一个供应者/消费者模式当中,两个端点之间没有直接的通信。不可能通过在一个阶段保证可靠性而达到整个通信过程的可靠。必须通过在各个不同的阶段保证可靠性,才能实现整个通信过程的可靠性。各个阶段提供的可靠性支持必须协调一致。下边我们讨论通知服务提供的可靠性支持。
2.2通知服务的事件和连接可靠性
在分布式系统中有许多消息传递策略,如尽力传输,最少一次,最多一次和仅有一次等。所有这些都只是针对点对点和请求应答式的通信模式。通知服务定义的是一种点对多点的没有应答机制的传输机制。
通知服务对事件和连接的可靠性分别进行了定义,分别使用了EventReliability和ConnectionReliability属性进行定义。这两个属性可以分别取Best effort或者persistent。前者设置事件的可靠性,后者设置供应者-事件通道-消费者传输通路的可靠性。在结构化事件格式中填入Reliability,实际是指EventReliability特性,因为一个事件是不能设置ConnectionReliability特性的。当EventReliability特性取Best effort时,通道并不对存储在缓冲区中排队的事件负责,在通道崩溃以后,这些事件会丢失;当EventReliability特性取Persistent时,通道对存储在缓冲区中排队的事件负责,在通道崩溃以后,这些事件不会丢失。当ConnectionReliability特性取Best effort时,通道不负责保存所有与之相连的供应者和消费者的对象引用。在通道崩溃以后,这些连接消失;当EventReliability特性取Persistent时,通道负责所有与之相连的供应者和消费者的对象引用,并在通达崩溃以后,试图重新建立这些连接。当然有时它会发现有些对象引用已不可用。如果把EventReliability的取值和ConnectionReliability的取值进行组合的话,就可以得到四种组合。其中:
<EventReliability=best effort,ConnectionReliability=best effort>:是最不可靠的,通道出现问题以后,事件会丢失,连接也不会被恢复;
<EventReliability=persistent,ConnectionReliability=persistent>:最可靠,通道出现问题以后事件不会丢失,连接也会被恢复。
<EventReliability=best effort,ConnectionReliability=persistent>:则是介于前两者之间,通道出现问题以后,事件会丢失,但是连接会被恢复;
<EventReliability=persistent,ConnectionReliability=best effort>:则是一个无意义的组合,因为如果通道出现问题以后无法保证恢复连接,事件即使被保存也无处投递。
三 基于通知服务的可靠的消息传递机制。
通知服务中的发送和接收(无论是Push还是Pull模式,或者混合模式下)操作并不是原子操作。通知服务并不提供任何的事务保证,这样的结果是,通知服务在设置了事件持久和可靠传输的条件下提供的事件传递语义是“最少一次”。
下边我们讨论通知服务如何应用在需要可靠消息传递的程序当中。我们假设程序需要消息的可靠和有序的传输,认为消息的可靠传输是指:消费者在消费者崩溃,通知服务崩溃或者网络连接失败的情况下,可以收到所有发给它的事件。消费者可以检测和容忍事件的重复。
3.1通知服务的事件传递语义
Push 模式
在Push模式下,如果一个供应者的Push操作没有返回,供应者必须重新Push,因为它不知道通知服务有没有处理过事件。供应者可能是在Push操作中出错,在通知服务收到事件并将事件存入持久性介质之后。当供应者恢复以后,因为它不知道最后一次Push操作是否成功,供应者就要将最后一个消息重新传输一次。所以不管是供应者或者是通知服务失败,都会导致事件的重复传递。供应者端的事件的重复是可以容忍的,因为可以通过事件的顺序进行区分。
在消费者端,通知服务在执行Push操作的时候可能由于消费者崩溃或者网络失败等原因收不到消费者的回复消息,但是消费者确实已经收到消息并进行了相应的处理。如果通知服务再次传递事件的话,将会导致重复。同样,如果通知服务在给消费者发送一个事件之后和向持久介质做标记以前崩溃,当它重新启动的时候会重新发送事件。所以消费者必须可以检测和容忍事件的重复。在事件当中加入事件的序号也正是为了解决这个问题。
Pull 模式
在Pull模式下,如果通知服务在Pull操作在供应者端成功执行以后和IIOP返回操作成功执行以前崩溃,事件将会丢失。当通知服务重新启动以后,它向供应者发出Pull操作请求,供应者将会向它发送下一个事件,如果供应者在更新了事件的序号以后和从Pull操作返回以前崩溃了,或者由于网络失败问题导致返回消息丢失,则出问题的消息将会丢失。这是因为当供应者从通知服务收到下一条事件请求的时候是不会在传递出问题的消息。
考虑Pull模式下消费者端,通知服务可能在对被发送的事件做标记以后和客户端发送的Pull请求结束以前崩溃,在这种情况下,通知服务重新启动以后它会根据消费者的下一条Pull请求发送下一条事件,这样就会导致事件的丢失。当一个Pull 消费者在发出一个Pull操作之后正在处理消息的时候崩溃,消息将会丢失,因为当消费者重新启动以后,通知服务将会向它发送下一条事件和下一条事件请求。
总的来说,通知服务Push模式支持的至少传输一次的语义,对于供应者和消费者都有可能会丢失事件,CORBA的通知服务的发送或者接收操作不可能通过一次事务完成。各种情况总结如下表:
模式 |
失败 |
后果 |
|
位置 |
类型 |
||
Push |
供应者端 |
供应者崩溃 |
事件重复 |
通知服务崩溃 |
事件重复 |
||
网络连接失败 |
事件重复 |
||
消费者端 |
消费者崩溃 |
事件重复 |
|
通知服务崩溃 |
事件重复 |
||
网络连接失败 |
事件重复 |
||
Pull |
供应者端 |
供应者崩溃 |
事件丢失 |
通知服务崩溃 |
事件丢失 |
||
网络连接失败 |
事件丢失 |
||
供应者端 |
供应者崩溃 |
事件丢失 |
|
通知服务崩溃 |
事件丢失 |
||
网络连接失败 |
事件丢失 |
3.2 可靠的消息传递机制
要实现消息的可靠传递,通常有三种基本的方法:(1)基于消息队列的方法。通过将消息存储到持久性介质,防止消息的丢失,实现可靠的消息传输。适用与松散耦合的进程间的通信。(2)事务处理监控器的方法。将事务串行化到持久介质,在事务环境中执行事务,通过两阶段提交和回滚机制实现可靠的消息传递。适用于分布式的数据一致性管理(3)虚拟同步技术。通过一个守护进程循环检测当前管理组里边的所有失效的对象和进程,然后重新启动保证消息传递的可靠性。适用于面向进程的,对象分布状态是暂态的情况。
本文基于CORBA的通知服务的消息队列的实现方法,同时借鉴了后边两种方法。进程S需要可靠的将消息M传递给进程R,首先将M放入本地消息队列的引用,在这里就是供应者代理,供应者代理将M写入持久性存储介质以免崩溃发生的时候消息丢失。消息提交以后,供应者就等候返回结果。消息的传递由消息队列里边的进程负责存储和转发消息。S的代理尝试向R的代理发送消息,如果传输失败,则守护进程根据情况重新启动相应的进程,同时S代理一直检测和发送直到成功发送消息。为了防止重复处消息,专门有一个单独的线程或者进程运行在一个事务环境中处理消息,保重的了每个消息只处理一次。
3.3 基于通知服务的可靠消息传递框架
Push 供应者 |
通知服务 |
Push 消费者 |
IR 守护进程 |
守护进程 |
实现库 (IR) |
工作线程/ /进程 |
持久事件存储 |
持久事件存储 |
ping |
图2 基于通知服务的可靠消息传递框架
通过上边的讨论,我们提出了一个基于通知服务的可靠消息传递框架,在客户端或者通知服务崩溃,网络连接失败的情况下,它最大限度地保证了消息传递的可靠性,如上图2 。下边我们以Push模式来解释整个框架。
对于一个Push 供应者来说,崩溃后的恢复是很简单的。所需要做的就是重新连接到通知服务,重新得到一个代理并连接到这个代理。它将会使用每次Push操作过程中标记的事件顺序号来正确的传输下一个事件。新的供应者将会销毁失效的代理对象,以免通知服务性能的下降。所以消费者代理的引用也必须被持久的保存。另外一种选择就是通过恢复它以前的信息重用以前的代理对象。但是通知服务的CallBack函数将不再可用,因为在消费者代理上边的供应者的对象引用已经失效。调用这样的函数将会抛出OBJECT_NOT_EXIST异常,同时销毁代理对象。因此使用第二种方案的话,需要经常使用一致的IOR启动供应者。
如果消费者崩溃的话,同样必须以一致的IOR重新启动。通知服务的下一个Push操作将会重新透明的绑定到供应者代理。为了灵活性更强,可以使用CORBA的IR(Implementation Repository)技术。使用IR技术的ORBs必须同时实现一个守护进程来和IR交互。使用这种守护进程可以实现消费者在任何主机的任何端口上重新启动(前提是消费者对象必须以以前的名字进行注册),这个守护进程负责参与重新绑定的过程,只有这样通知服务才可以知道新的消费者对象的位置。当重新绑定成功以后,守护进程和IR都不参与消息的传输过程。
如果至少传输一次的语义对于消费者来说是不可接受的话,可以使用顺序号信息来检测事件的重复。但是如果消费者在事件处理以后和接收操作返回以前崩溃了的话,那么消费者将无法检测到它恢复以后的第一条消息的重复。图2提供的框架实现了每一个事件只处理一次的解决方案。在Push操作中,消费者借助于事件的序号,只存储一次事件。即使出现重复的事件,也只是重写了上次的事件。一个单独的进程或者线程专门负责读取事件,并且在一个事务上下文(为了保持操作的原子性)中处理这些事件。
如果通知服务崩溃并重新启动了,它里边的所有对象都需要重新创建,所有消息队列里边的事件需要从持久性介质中读入并重新构造。因此通知服务的状态必须被持久的存储。这样通知服务的失败或者重新启动对于Push 消费者来说都是透明的。当通知服务失败的情况下,如果供应者正在发送消息,那么这个消息在通知服务重新启动后将会成功的传输。图2中的ping守护进程周期性的检测和重新启动失败的通知服务。对于重要的事件,高可用的通知服务是必须的。
四 结束语
本文讨论了基于CORBA通知服务的可靠消息传递技术。提出了一个可靠CORBA消息传递框架。通过在实际电力监控系统中的运行的情况来观察,是一种可行的可靠消息传递解决方案,并且可以做到重复消息的检测和容忍。通过本文的讨论,可以看出通知服务提供的消息传递支持和为了实现可靠消息传递所要考虑的问题。
参考文献:
[1] 朱其亮,郑斌. CORBA原理与应用 [M]. 北京:北京邮电大学出版社,2001
[2] 高建军,吴健. CORBA服务在分布式电力监控系统中的应用. 计算机应用与软件 2005(5)
[3] Gruber, R.E.; Krishnamurthy, B.; Panagos, E.; CORBA Notification Service: design challenges and scalable solutions,2-6 April 2001 Page(s):13 – 20.
[4] Borland Software Corporation. VisiBroker for C++ programmers guide. Version 4.5
[5] Sean Landis, Building Reliable Distributed System with CORBA,1997.