(转)WebService的事务处理

若是你只是要解决两个系统之间的事务同步问题,能够采用判断服务是否成功的办法来解决,即:
    
    * A系统开始本身的事务,处理本身的数据,而后。。。
    * 在提交以前调用B系统的服务。
    * B系统开始本身的事务B,在事务中处理数据,再提交事务。
    * B系统把本身事务的提交成功与否的信息作为返回值回馈A系统。
    * A系统根据B的事务成功状况决定本身的事务是否提交或是回滚。
 
    可是,在继续深刻讨论这个问题以前,先反问一个引申的问题:当分布式系统之间,要进行事务控制的子系统不是两个,而是N个时,若是进行事务控制?
 
    分布式事务一直都是很难解决的问题。在面向DCOM的分布式应用中,有一种分布带事务支持策略,大致的思路是采用两段式事务提交的办法,第一次提交是预提交,预提交以后是能够回滚的。第二次提交是永久性的提交,提交以后就不能够回滚。而且,若是预提交成功,第二次提交也必然成功,系统必须能够保证这一点。
 
    这样,当每一个系统都支持这种两段式提交以后,就能够采用这样的事务管理:一个控制角色向每一个分布系统提出执行要求,并要求完成第一次事务提交。当每一个系统的第一次提交都成功时,则要求全部系统完成最后的永久提交,可知此次的永久提交是确定能够完成的,所以不需要再担忧此次提交是否成功。
    若是第一次提交中,有某些应用出现失败,则要求全部的应用都回滚事务。
    一些数据库软件自己就支持事务嵌套,如sqlserver等,不幸的是,咱们的主力数据库informix不支持。
    为了简化这种分布式事务管理,有一些中间件产品能够采用,用得比较普遍的是MS DTS.
 
    你可能已经看出来了,这样的事务控制策略虽然能够在分布式环境下知足事务的ACID要求,可是它对各个分布组件是有要求的,在基于COM, remoting,JRMI一类技术的分布式应用程序中,这个没有问题。可是在采用web service的场景中,这是有问题的。
 
    问题1. web service是一种以松耦合为指导思想的集成方式,通常状况下,主张采用无状态方法。
    webservice主张两次调用之间没有上下文关系,即一次调用与其余以前和以后的调用都没有关系,一次提交即完成一次完整的处理。可是分布式事务却要求各方要在两次对话之间保持对话状态,以便于知道本次永久性提交时,要对以前“哪个”已经被预提交成功的事务执行最后的提交。
    当遇到这个问题时,咱们必需要再多问本身一个问题:咱们已经选择了正确的集成技术吗?若是多个系统之间有如此紧密的事务耦合关系时,我很怀疑它们其实就是同一个应用系统。同一个应用系统中,应该有相同的平台,相同的进程空间,相同的数据模型以及数据源。这种状况下,采用web service是一种错误的选择,web service应该用于不一样平台、不一样应用、不一样的数据模型的系统集成。即使是的确须要在同一个应用系统中因为某些缘由而实现模块间的分布式构造,也应该采用同一技术平台内的远过程访问技术,它们能一般比web service能提供更好的耦合性支持。
 
    好吧,假设你通过思考以后,对上述问题的回答是“是”:咱们确实必需要在异构的、多平台的、原本应该是低耦合系统之间实现分布式事务控制。那么,webservice还有用处吗?
    谢天谢地,web service虽然主张交互之间采无状态方式,可是它并非禁止采用有状态的交互。WEB SERVICE仍是一种web技术,而web技术中的状态保存多是最先被解决的问题之一了。在全部的web开发技术平台中,都有session机制,不管这些Session是经过IP,cookies, hidden input来实现,仍是url sessionid来实现的,反正都有办法实现,请参阅所用平台的session支持机制就能够了。退一万步,你也能够经过在服务器中维护一个应用程序级的事务池来实现,未最后提交的事务对象都放在里面,每个事务对象都给定一个惟一个的标志ID来识别,造成一个字典对象池。若是启动事务成功,则把此事务的ID返回给调用者执有,作第二段提交时,把事务的ID作为参数提交就是了。(随便提一下,用这种方法时,千万不能把对象的指针、句柄、引用什么的平台相关的值交给客户方,倒不是惧怕安全问题,而是这些值在分布系统中是没有意义的,上次返回的指针没准早被垃圾收集机挪到其余地方去了)
 
    不管如何,webservice在通讯层上是一种无链接的协议,每两次调用之间,tcp链接是断开的,所以,一但采用session机制来管理上下文,你就必须为这些session的生命期负责。试想,若是一个事务上下文已经开启,而此时客户方系统却忽然当机了,这时会出什么事情?在同一个应用程序域中,客户方的当机会让链接中断,服务器当即就会中断并回退事务,可是在webservice里,状态管理机没法当即感受到此事务的调用方已经失去控制,只能在必定的时间以后,才发现:“噫?这个事务已经N长时间没有人访问了!快快回退!”在ASP.net里,默认的状态超时时长大概是20分钟,JSP也差很少,阻塞了20分钟的事务对数据源是什么影响可想而止!所以,必须考虑合适的状态时长与事务隔离级别,以减少对数据源的性能影响。       
 
    问题2. web service的“反模式”方法论使得没法在系统之间统一出共同的抽象接口。
    web service是一种“反模式”的系统架构思想,即不是通常的由先建模并抽象接口开始,再由各个分布系统实现接口的系统构造方式,而是反过来:系统可能早已经完成,如今的问题是两个系统间的信息交互做用,所以交互的接口规格是根据须要,把系统数据模型去范式化后挑挑捡捡而定的。
    所以,webservice中不支持接口抽象,即:你没法定义一个各个系统都必须实现的抽象事务接口,而后由各个系统实现这个接口的多态,最后在承担事务控制器的应用中调用统一事务接口以调度分布事务。虽然这样的接口模型在不少面向对象的开发平台中的远过程调用技术中所支持,可是如同以前说过的,web service是一种用于集成的松耦合的反模式方法论,而不是为紧耦合系统中的分布式对象而设计的。
    因此,虽然有点讨人烦,可是我又一次忍不住想问我已经问过的那个问题:咱们真得用对了技术吗?若是多个系统之间须要如此级别的接口耦合性,我真得愈来愈怀疑它们其实就是同一个应用系统了。
    假设你的回答仍是“是,他们真得不是同一个系统,他们是异构平台的,异构数据的!”好吧,那么继续。让咱们采用web service来完成集成,可是你必须忘记你的OOP思想,老老实实地编码,用枯燥的、重复的代码把全部的系统的事务都控制在一块儿,别想用对象抽象的概念来省一点事。
    真的吗?
    若是把事务控制器独立出来如何?假设咱们创建一个专用于分布式服务控制的应用,而用WEB SERVICE的方式公布接口, 容许其余应用程序经过向这个事务控制器注册本身的两段式事务开启、提交和回退的web service接口。而后,当有客户想启动分布事务时,就能够向这个事务控制器发起分布式事务请求,选择事务各方,启动一个分布式,最后向事务控制器,而非是各个事务方直接发起提交请求,这样事务控制的多态就能够在事务控制服务器中实现,虽然实现可能仍是经过查表等方式实现,而非平台级的抽象方法,可是对于事务客户来说,这样一个服务器就是多态的实现部分。
    若是真得比MS更快更好地实现这样一个web service作接口,面向异构系统的分布式事务控制器,NASDAQ也许会有你的一席之地吧!
 
    问题3. 异构平台不必定都支持两段事务提交模式。
    web service面向的是彻底异构平台的集成,那么显然不能期望每一个平台都能支持两段时提交事务模式。可是,标准就是标准,协议就是协议,标准就是用来让你们遵照的,若是一个平台原本不支持两段式事务,那么为了能支持分布式事务,它就必须改造以实现两段式事务提交。
    怎么改造是各个应用系统内部的事情,为了本文讨论的全整性,也在这里稍微涉及一下。
    首选的方式是经过数据缓存的方式来实现。不少OO系统中,都采用了所谓的N层架构,即把业务对象与关系表模型分离开来,业务对象位于系统内存或是缓存中,由运行时的对象容器管理,容器根据必定的策略,把缓存中业务对象向数据库这样的久永介质中保存,或是从数据库中加载所须要的业务对象,在保存和加载过程当中,将完成对象到表数据的转换,或是相反。web

    通常的N层结构的中间件产品中,都会提供两个级别的事务,即面向缓存中对象的事务控制和面向持久化过程的事务,能够考虑简单地将此两个事务级别对应的分布事务中的两段事务提交。可是,这种方式必须冒必定的风险,如对象容器级的事务成功,而数据库事务提交时出现失败,此时将会致使的数据不一致的风险,尽管这个概率并不很大。sql

    在使用数据容器的状况下,也能够用保存对象的历史状态来实现事务的手工回退。由于在业务对象层与持久化层相分离以后,持久化层在数据更新时并无复杂的逻辑,只是一些被罗列的、业务意义无关的数据更新序列。若是能够保持对象的状态历史,那么就能够在须要的时候将对象的状态恢复到旧的旧版上。实际上,在一些出色的中间件平台中,这个机制已经实现得很是完善了。(能够参阅Graphtalk平台的对象持久化管理,简直是天才!)数据库

    另外一种笨办法是经过数据逻辑来实现两段事务提交,例如在要求第一次提交时,即真正提交,在第二次提交时固定什么也不作,而返回正常。若是要求回退,那么就经过数据逻辑或是业务逻辑来更新数据为旧状态。这种实现方式绝对是很使人头痛的。缓存

    不过,幸好咱们不是在为一个通用的数据库设计两段事务机制。要知道,面向服务的事务处理并非如同数据库级别的事务那样,在事务的期间数据的操做有无穷的可能性。一般咱们一个服务就是一个功能,其数据操做过程当中,数据的变化方式是可预知的,所以恢复数据的状态也是一个个具体而固定的过程,只要咱们针对每个服务操做设计数据恢复机能就是了。安全

    最后,若是这些都不可能实现的话——大于50%的可能性,由于时间、成本、技术等缘由,这些都实现不了,那么只能靠两个字了:妥协。服务器

相关文章
相关标签/搜索