业务组要求ASF提供多种方式的远程服务访问,兼顾性能和跨平台的不同需求,因此在原有的Web
Service的SCA发布及绑定的功能外,集成了Hessian,用以发布和访问内部服务(安全性和跨平台要求不高,性能要求较高的服务)。在文中将要讲的就是如何将一个外部的开源项目集成到基于SCA规范实现的服务框架中。
注:ASF(Application Service Framework)是基于Tuscany作为解析内核,再次封装和扩展的符合SCA规范的服务框架,SCA基本元数据解析依赖于Tuscany内核部分,组件解析组装以及扩展根据SCA规范实现。
设计与实现
根据需求并且结合SCA的extend规范,只需要采用binding extension的方式,提供实现:
1.在ASF框架中将业务发布成Hessian服务可被ASF内部服务组装调用。
2.在ASF框架中将业务发布成Hessian服务可被外部调用。
3.ASF框架中的服务能够绑定外部发布的Hessian服务。
扩展插件实现步骤:
1. SCA配置的解析。(采用实现StAXArtifactProcessor接口)
Read是读入配置文件时应该如何解析标签中的内容,write是动态将运行期内容写入到配置文件中(一般应该很少用)。getArtifactType是返回所要解析的具体内容,也就是后面要提到的Model。Resolve是根据SCA配置文件解析的结果和通过已经解析的一些资源作再次的逻辑组装,应该算是业务逻辑的解析处理。
2. 创建Hessian服务的发布提供实现以及调用绑定提供实现。(此处的切入点是实现BindingProviderFactory)
提供了创建服务绑定提供的接口实现和服务调用绑定的接口实现。
3.将扩展插件接入到ASF框架中(采用实现ModuleActivator接口)
只有开始和结束模块插件的两个方法,这儿就是将上面两部分需要注册的内容注册到服务框架中,服务框架根据需要解析的Model来做处理。这里和上面都提到了Model,同时也可以看到上面两个接口都是采用泛型的设计,其实所有的处理都是围绕着Model来做的,后面会有全局的类图,就一目了然了。
Hessian绑定插件全类图(分成了三块作为图形展示):
这部分类图中的四个类相对来说比较独立,其中HessianBindingProviderFactory和HessianBindingActivator已经解释过了,前者的作用在于产生Hessian
Binding的服务提供者实现和引用者实现,后者是作为注册到服务框架中去的接入点。ASFHessianServlet在第一次开发过程中是没有实现的,直接采用HessianServlet去处理远端Hessian请求,但是在后续的测试过程中发现了问题,就扩展了HessianServlet,后面会提到此问题。ASFHessianConfigurator是对Hessian服务提供者提供一些必要的配置信息。
这个类图囊括了Hessian服务提供者和调用者的实现以及与Hessian
Model之间的关系。可以看到服务的提供者和调用者都是围绕着HessianServiceBinding来定义操作。HessianServiceBinding是扩展了Binding和Extensible的一个接口,由于在前面已经提到,当前所要做的扩展只是Component中的Binding,因此继承了Binding接口,同时作为良好的可扩展性,继承了Extensible接口,允许继续被扩展
HessianServiceBindingImpl是Binding扩展的具体实现,内部包含了在扩展标签中所包含的属性,用来提供给Binding服务提供者和Binding服务引用者使用。在服务的真正提供者和调用者的实现外部多做了一层封装,用来提供例如回调和异步服务处理的机制。
上图中几个类主要负责SCA标签解析实现,通过工厂类动态组装解析实现,然后将工厂类注册到ASF解析扩展库中,在解析到对应的Qname的时候调用工厂类来生成解析器去解析配置信息。
Hessian绑定插件流程图
上图描述的是基本的几个流程:插件的解析与注册, Hessian服务的发布与绑定,
Hessian服务调用和处理。
问题
1. 插件载入先后的问题。
Hessian需要内嵌Web Container支持,当前ASF框架中内嵌了两个Web
Container:Tomcat和Jetty,自己倾向于使用Jetty作为轻量级的内置Web Container。但是在插件载入初始化的过程中有依赖于Jetty插件,但Jetty插件还没有被启动,导致了Hessian插件无法启动。解决方法就是在Hessian插件激活的配置文件中,将Jetty也一起启动(支持一个文件配置多个插件),然后Jetty放置在Hessian前面。这个解决了启动的问题,但是可能导致重复启动多个相同的插件,以后需要考虑根据插件启动的情况来判断是否已经启动插件,只需要使用现有已启动的插件,防止重复启动,浪费资源。
2. 需要注入服务的服务作为Hessian发布的问题。
问题描述:
将某个接口实现发布成为Hessian服务,如果此服务定义需要注入其他ASF中的服务,注入失效。
问题定位:
开始设计服务端提供服务的时候,只是简单的将所需要发布的服务接口和实现传递给HessianServlet,然后让HessianServlet自己创建逻辑实现来处理,但是这样每次都是简单的通过实例化来构造业务处理对象,根本没有去读取配置文件来注入ASF的服务。
问题解决:
重载HessianServlet,通过服务发布提供者构造时传递给HessianServlet所需要使用
的ASF内部组件,在Servlet的service方法中用组件创建业务Proxy,然后调用具体的方法并返回结果,这里的Proxy已经将需要注入的服务注入到了业务逻辑实现中。
集成看扩展
SOA的缩略版
在SOA的技术实现设计中,最简化的方式就是一个中心三个角色。一个中心就是服务为中心,三个角色就是服务提供者,服务消费者,服务的发布者。
对于面向服务的SCA框架来说扩展也是延续了这种设计模式,框架的作用就是类似于ServicePublisher的角色,然后需要插件的开发者提供另外两种角色,同时为了更好的结合其他资源融入到服务实现中,还提供了Resource
Resolver角色用来支持类似于wsdl,spring的配置xml等文件的解析,提供给服务发布者使用。
工厂模式的用武之地
在IOC思想出来之前,工厂模式应用很广泛,通过工厂模式在应用中来绑定不同接口的实现。但是实践证明工厂类的滥用导致了系统耦合性增强,很难做模块的独立单元测试,最后甚至影响了整个架构的可扩展性和需求变更响应能力。
当IOC出现以后工厂模式基本就被废弃了,服务之间的组装通过配置来完成,各种框架都充当组装者的角色,通过Proxy方式能够Lazy
instance。但是作为框架级别的开放扩展,可能都根本不知道服务实现提供者,因此这种组装就无法满足。例如JSR
173对于Stax的设计实现来看,就采用了工厂模式结合策略文件的读取来运行期载入服务提供实现的方法。其实现在各种扩展性好的框架都采用了这种方式来支持扩展点的接入。
当看到很多开源项目中的SPI包时,往往就会提供这样的服务提供接口扩展实现方式,动态的支持第三方再次开发并且集成到开源框架中。所以只有使用的恰当与不恰当,没有说某一种模式或者技术有好坏之分。
插件间的协作反看SAAS平台中服务的协作
在问题部分提到了关于插件间的协作,这里的协作耦合的很紧,基本上是一个插件直接调用了另外一个插件的接口。这种方式使用简单,效率高,但是耦合性比较强,同时在服务接口定义上个性化比较强,无法作为一个通用服务接口集成到平台中,提供给平台以及其它业务使用,不过这个可以通过类似于ESB的方式来解决。不过反看SAAS平台中各种应用的集成,如果没有能够使得各种应用互通互用,那么就无法最大化应用的价值,应用本身也就成为了一个个独立的“孤岛”,用户无法定制个性化的服务,大大削弱了SAAS模式的优势。设计和抽象出交互接口,提供给业务应用实现和调用,那么将会成为SAAS平台服务的关键。
后语
常常有朋友问我,将Spring,Web Service都集成在SCA中使用比单独使用Spring,Web
Service要麻烦的多,SCA有什么好处?其实这就是把SCA当作了具体的技术实现规范而不是框架约束规范。我可以用Spring去实现SCA规范,也可以类似Tuscany用java基本原语去实现,这只是手段的不同。面向业务组件进行封装,组合,调用,这些才是SCA框架规范的精华。
同样的,任何一种技术其实都不会凭空产生,SCA也是在经历了面向对象,面向组件,面向服务的积累,将框架设计中抽象提高到了服务,能够满足当前互联网应用的快速响应用户需求变更,灵活组合定制的需求。
最近看到有一篇文章的题目为《SCA让程序员走开》,好奇之下看了一下,其实也是指很多开发人员对于SCA框架的误解。但在我看来应该是SCA让程序员走近看看,架构师和程序员总有着矛盾,这只是两种角色看问题的角度不同,程序员最根本的职责就是高效,高质量完成开发任务,至于采用什么方式和技术优先级放在第二,而架构师的职责是从总体和长期上把握整个项目的进度按时完成,提高响应变更能力,降低维护成本。其实双方是不冲突的,只要架构师在设计的时候能够多考虑开发的便捷高效,程序员能够从复杂的开发过程中解放出来多参与架构设计的学习,那么就可以互相理解形成良性循环。SCA规范是否能够很好的实施关键在于人,如何将面向服务复用的思想通过简单的开发方式展现给程序员,提高程序员的开发效率,测试效率,那么就可以事半功倍。程序员多参与SCA框架的扩展设计,可以提高对于框架的理解,并且提高自身的设计能力与架构师达成共识。
不必太在意SOA,SCA,SAAS,WEB2.0等等词汇,需要了解的只是这些概念背后真正对于现实有指导意义的内容,学会用这些内容去指导工作实践,那么才不会漂浮在空中,成为“空中飞人”。 |