技术开发 频道

浅析Web Service模式中的Service Observer

【IT168 管理】随着SOA化,服务对象间经常出现一对多的依赖关系,当某个Source服务发现出现新的情况下,常常需要同时通知到多个既定目标服务(Target服务)。另外,如果必要的话,Source服务还需要通知Target服务进行某些更新。

问题 

    Web Service作为一个彻底的分布式系统,按照软件职能的需要常常被分割为多个服务,但其中经常存在一些对象,它们的内容对其他服务而言是参考信息(比如新的汇率、不良的信用记录等),其他服务如果总是通过分布式调用轮循访问这些信息,从效率上、服务设计上都不恰当,这时候,Source服务最好可以在相关事件发生的时候根据需要通知到其他Target服务,告知相关的参考信息,保持多个Target服务中相关信息的一致性。 

    下面按照设计模式中Observer模式的称呼,我们把Source服务称为Subject,将Target服务称为Observer。 

    上面仅仅介绍了一种单向的模式,也就是Subject自身发生变化后,把信息“推”到每个Observer的情况,但在实际企业环境中很少有这种“无中生有”的系统,实际情况往往是这个Subject本身还会偶尔接收某个Observer的输入,更新某些信息后,再告诉其他Observer。 

    还有一个问题:Subject之前是怎么知道它要通知的各个Observer呢?注册就好了么?对于一个SOA环境而言,服务的注册一般由Service Registry/Repository完成,这样重复建设等于“坏了规矩”。那么Subject应该怎么做呢?在Subject一方定义一个对Observer服务依赖反转的Observer Service Registry Stub,与集中的Service Registry/Repository不同的是,这个Registry Stub仅仅定义可以预订自己内容的Observer,虽然增加了Stub但从定义上讲Subject他还是自治的。

资源争用

    从资源使用的角度看,一般Subject对修改是限制的(每个资源一次仅允许一个Observer修改),对查询是开放的,所以在可写Subject模式下,随着Observer的增加,Subject中具体资源的“读/写”比为N:1(N为Observer数量)。为了有效控制这个并发过程,需要增加一个适合的锁——多读单写锁(ReaderWriterLock)。同时从Subject向Observer发送通知的角度看,由于这种Web Service调用效率上相对于本地内存调用存在很大的差别,如果不加控制很容易在接手端造成通知到达次序颠倒的情况。如果应用逻辑中对这个颠倒不敏感,那么Subject就可以借助Stub中登记的Observer,尽最大可能发送通知。但如果应用上下文,严重依赖这个次序,那么需要在Subject发送通知前增加一个Gateway,确保发送端、接收端次序保持一致。

数据内容的筛选 

    上文的讨论中回避了一个问题,就是信息内容本身,一旦出现更新的时候是Subject把某块信息全部推到Observer,还是仅仅把更新后的内容推下去。这里有两个因素需要考虑:

1、 相对于进程内的内存引用交换,Web Service算是非常昂贵的调用,不仅仅有数据准备,还需要进行XML数据的序列化、反序列化,传输过程中还会被HTTP和TCP进行反复包装,因此如果更新内容仅仅占整个数据内容很小一部分的时候,应该对发送的消息进行筛选。

2、 Web Service中交互的数据本身是XML数据,它具有自身描述性,因此可以很容易通过XPath或者XQuery在Subject一端进行抽取,并在Observer进行更新(一般这个过程可以称之为两个XML数据的Merge)。 

    由于实现相对简单,但对于减少Web Service数据量比较有效,因此考虑增加一个数据Assembly,用于数据实际更新前选择有必要更新的数据。

耦合关系分析 

    虽然Subject需要同时和多个Observer交互,但因为是每个Observer自己向Subject注册,因此在Subject一端看到的都是抽象的IObserver接口,而不包括实体Observer类型,因此Subject与每个Observer之间没有明显的耦合关系。在Observer一方,实际上很多时候并不知道具体的Subject是什么,如果让每个Observer与实体Subject耦合,设计上也相对比较“密”,不妨将相关工作交给一个统一的根据配置文件动态组装的Assembly,专门负责将某个Observer 绑顶到具体的Subject上。

组合关系

    使用上Subject往往仅针对某个具体内容,而Observer往往关心的不只一个Subject所能提供的内容,一种可以通过改造上面说的Observer Assembly,同时把Observer装配到不同的Subject上,另一种可以在保持每个Observer仅仅接收单一Subject通知的前提下,为Observer增加组合关系。


0
相关文章