4. 基于OSGi搭建分布式系统
OSGi 规范是基于同一 VM 而设计的,因此并无对于分布式通讯的支持,分布式的通讯有很多种实现方法,如采用 RMI、基于 MQ、SOA 等方式,SOA 无疑是目前分布式领域中为流行的架构体系,在本章节中就以一个实例来分析基于 OSGi 如何搭建一个实现像 SOA 这样的脚手架。
4.1. 实例需求
仍然以留言板系统为例,现在要求管理员登录的校验服务部署至另外的一台机器上,这也就意味着需要能够分布式的调用其他 OSGi 应用中的服务。
4.2.搭建基于OSGi的分布式系统的脚手架
根据需求,要求能够远程调用其他 OSGi 应用中的服务,SOA 是一个典型的分布式架构体系,在 SOA 的架构体系中,要求系统以服务的方式对外提供功能,同时以发起服务请求的标准方式获取其他系统提供的服务,OSGi 是按照面向服务的思想而设计的,因此其和 SOA 架构体系可以很好的融合在一起,区别就在于 OSGi 是针对同一 VM 环境下的,并不支持分布式,为了让 OSGi 应用能够互相通讯,可采用 web service 来实现,在这里我们来搭建一个这样的脚手架,使得 OSGi 应用之间可通过 web service 来进行通讯。
封装 Axis 在此我们选择 Axis 做为脚手架中支持 web service 方式调用的框架,参照 Axis 部署至应用服务器的方法,建立一个如下目录结构的插件工程:
AxisBundle
| -- src
| -- WEB-INF
| -- server-config.wsdd
| -- lib
| -- META-INF
| -- MANIFEST.MF
将 Axis 所需的 jar 放入 lib 目录中,编写一个 Component 调用 HttpService 注册
Axis 中的 AxisServlet 和 AdminServlet。 在注册完毕 AxisServlet 和 AdminServlet 后,要显示的调用下这两个 servlet 的 init 方法:
AxisServlet axisServlet=new AxisServlet();
AdminServlet adminServlet=new AdminServlet();
if(http!=null){
try {
http.registerServlet("/"+AXISWEBCONTEXT+"/services",(Ser vlet)axisServlet, null, null);
http.registerServlet("/"+AXISWEBCONTEXT+"/servlet/AdminS ervlet",adminServlet, null, null);
axisServlet.init(); adminServlet.init();
info("成功注册Axis相关Servlet!");
}
catch (Exception e) {
error("注册Axis相关Servlet时出现错误", e); } 提供调用远程 OSGi 服务的接口 此插件工程需要对其他 Bundle 提供调用远程 OSGi 服务的接口,这个接口的代码如下所示:
/**
* 调用远程OSGi服务
*
* @param serviceName 服务接口名
* @param methodName 方法名
* @param target OSGi服务所在机器IP
* @param port Web服务端口
* @param args 传入参数
* @return Object
*/ public Object invokeService(String serviceName,String methodName,String target,String port,Object[] args);
此接口按照 Axis 调用 webservice 的方法实现即可,具体请参见
RemoteOSGiServiceCallerComponent 代码。
提供执行同一 VM 中的 OSGi 服务的 WebService 此 WebService 根据请求的服务名获取同一 VM 中的 OSGi 服务,基于 java 的反射机制传入参数执行并返回相应的值。 接口代码如下所示:
public Object invoke(String serviceName,String methodName,Object[] args);
在编写完此类后在server-config.wsdd中加入如下内容即可将此类以webservice的
方式对外提供:
经过以上三步即完成了支持远程调用 OSGi 服务的脚手架的搭建,下面基于此脚手架来实现管理员登录的校验的需求。
4.3. 实例的实现
根据需求,管理员登录的校验需要调用位于远程或另一 VM 下的登录校验 OSGi 服务,首先需要建立一个新的插件工程来提供登录校验服务: 这个工程只需要对外 export 登录校验服务的接口即可,此接口的代码示例如下:
/**
* 登录校验服务
*
* @param username 用户名
* @param userpass 密码
* @return boolean
*/
public boolean check(String username,String userpass);
接着建立一个插件工程来实现登录校验服务,并将此实现作为 OSGi 服务对外提供; 后就是重构之前的管理员登录模块,将登录校验改为调用远程的 OSGi 服务来实现: 在管理员登录模块中 import 登录服务接口的 package ,重构之前的
CheckAdminLoginAction,将其中校验的部分改为调用远程的 OSGi 服务来实现:
Boolean returnValue=(Boolean) caller.invokeService(LoginService.class.getName(),
"check", "127.0.0.1", "1220", **new** Object[]
{txtUser,txtPass});
在完成以上步骤后,部署新的留言板应用: 根据需求,需要将留言板应用部署为两个 OSGi 应用,其中一个 OSGi 应用中包含了之前留言板应用的所有模块:
另一个 OSGi 应用中仅包含登录校验服务模块、登录校验服务实现模块以及 Axis 封装模块:
将这个 OSGi 应用的 web 端口设置为 1220:-Dorg.osgi.service.http.port=1220 启动这两个 OSGi 应用,在登录时可看到在登录校验的 OSGi 应用的 console 中打出了调用的信息,经过以上的步骤就完成了一个演示分布式调用 OSGi 服务的留言板。
4.4. 小结
在这个章节中实现了一个简单的基于webservice的分布式的OSGi应用通讯的脚手架,并基于此重构了留言板应用以演示脚手架的作用。 编写这个章节主要是为了说明基于 OSGi 来实现分布式的系统是可行的,尽管这里面还有诸如分布式的事务等等复杂的企业应用领域的问题没有展示如何解决。 不过这个章节中产生的脚手架和SOA架构的实现还是有很大的差距的,SOA需要有服务的集中注册和统一智能寻找的场所,这个可参考或直接采用SCA 的实现:Newton 或Tuscany ,或者大家可以根据自己项目/产品的需求来重构这个脚手架,让它成为一个更加实用的脚手架。