论坛首页 Java企业应用论坛

关于远程调用(XFire/HttpInvoker/Hessian etc.)及远程服务管理的一些随想(上)

浏览 7185 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-03-18  
<o:p></o:p>

在现代 J2EE 企业应用系统中,存在着 Hessian HttpInvoker XFire Axis 等多种形式的远程调用技术。尽管有 Spring 等框架对这些技术进行了封装,降低了使用的复杂度,但对普通程序员而言仍是复杂的——至少需要要掌握这些技术的基础知识。

<o:p></o:p>

无论使用那种技术,其基本原理都是一样的:服务端生成骨架,对外暴露服务;客户端生成服务代理,访问调用服务。通常情况下,生成服务代理的代价比较高昂,这也是我们第一次访问远程服务速度比较慢的原因,为每个请求生成新的服务代理恐怕不是我们所期望的。更何况,如果采用这种方式,就要在代码里针对各种不同的技术(如 XFire HttpInvoker )编写不同的服务生成和调用的处理代码。不仅麻烦,而且容易出错。我想,没有人愿意去直接操作各种框架技术的底层代码,这并不是一个好注意! <o:p></o:p>

<o:p> </o:p>

作为一种替代方案,我们设计了一个“服务池”的功能,或者说“服务工厂”更贴切一点。先看下面这张类图:

如上图所示,针对 HttpInvoker XFire Hessian 等各种远程调用技术,抽象出一个“远程服务池”(服务工厂)既 RemoteServicePool 接口。该接口提供了获取服务及一些其他的辅助功能,并针对 HttpInvoker XFire Hessian 等不同技术提供了相应的具体实现。采用这种方式,开发人员只需在代码中“注入” RemoteServicePool ,并以统一的方式(如 getService() )获取实际的服务,只是针对不同技术在配置上有些须差异而已。该技术的原理非常简单,在应用启动之前把所有存在的服务提供者提供的服务都配置好,并为它们分配一个唯一的 ID 。应用启动之后,框架会自动生成和这些地址相对应的服务代理( ServiceProxy ),这些代理已经是可用的服务,服务获取的细节被完全屏蔽掉,开发者只要知道如何从 RemoteServicePool 中获取服务就可以了。看一下服务池的接口定义:

<o:p>
java 代码
  1. /**   
  2.   * 远程服务缓冲池。   
  3.   *   
  4.   * 

     

     
  5.   * 对于一个既定的服务契约(既接口),可以有很多服务提供者(  ServiceProvider  )。该接口的提出,是为了解决服务访问者和服务提供者之间 “ 一对多 ” 的关系。   
  6.   *   
  7.   * @author Tony   
  8.   */    
  9.   
  10. public interface RemoteServicePool {    
  11.   
  12.     /**   
  13.      * 从缓冲池中获取一个  Service  。   
  14.      *   
  15.      * 

     

     
  16.      * 此处获得的是一个  Object  ,需要调用者自己做类型转换。   
  17.      *   
  18.      * 

     

     
  19.      * 参数  serviceId  代表服务缓冲池中的一个实例名称。服务类型采用配置文件中默认的类型。   
  20.      *   
  21.      * @param serviceId   
  22.      *             实例名称   
  23.      *   
  24.      * @return 服务对象   
  25.      */    
  26.   
  27.     Object getService(String serviceId);    
  28.   
  29. }   

 

xml 代码
  1. <bean id="userServicePool" class="com. tonysoft .common.XFireRemoteServicePool">    
  2.    <property name="serviceInterface">    
  3.        <value>com. tonysoft .demo.service.UserServicevalue>    
  4.    property>    
  5.    <property name="serviceUrls">    
  6.        <map>    
  7.           <entry key=" server 1 ">    
  8.               <value>http://localhost:8080/server1/service/userService?WSDLvalue>    
  9.           entry>    
  10.           <entry key="server2">    
  11.               <value>http://localhost:8080/server2/service/userService?WSDLvalue>    
  12.           entry>    
  13.        map>     J2EE 企业应用系统中,存在着 Hessian HttpInvoker XFire Axis 等多种形式的远程调用技术。尽管有 Spring 等框架对这些技术进行了封装,降低了使用的复杂度,但对普通程序员而言仍是复杂的——至少需要要掌握这些技术的基础知识。 <o:p></o:p>
  14.    property>     接下来看看如何配置服务:
  15. bean>    

最后再来看一下访问服务的代码:

java 代码
  1.   /** 服务工厂 */    
  2.     public RemoteServicePool userServicePool ;    
  3.     /**   
  4.      * 测试新增一个不存在的用户。   
  5.      */    
  6.   
  7. public void testAddUser() {    
  8.   
  9. UserService       userService = null ;    
  10.         try {    
  11.             userService =(UserService) userServicePool .getService("server2");    
  12.         } catch (Exception e){    
  13.             throw new RuntimeException( " 获取服务失败,失败原因:" + e);    
  14.         }    
  15.   
  16.         OperateResult result = userService .addUser( new User( "daodao" , " 技术部" ));    
  17.   
  18.         assertEquals(result.isSuccess(), true );    
  19.   
  20.     }    

该方案还为“双向关联”的系统服务提供了一个很好解决办法。看下面一张图:

 

    如图,系统 B 和系统 C 都调用系统 A 进行付款操作;同时系统 A 要用远程服务向系统 B 或系统 C 进行认证操作,认证操作的接口(契约)都是一样的,业务逻辑可能有所差异。在这种情况下,配置在系统 A 中的认证服务就比较麻烦,因为要根据不同的系统调用认证服务,既从 B 过来的请求要访问 B 的认证服务,从 C 过来的请求要访问 C 的认证服务。用服务池可以很好的解决这个问题,把两个系统( B C )提供的认证服务地址都配置在同一个服务池中,根据不同的 ID (如 B C )来决定使用那个系统的服务。

关于远程调用(XFire/HttpInvoker/Hessian etc.)及远程服务管理的一些随想(中)

关于远程调用(XFire/HttpInvoker/Hessian etc.)及远程服务管理的一些随想(下)

</o:p>
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics