Karaf教程第8部分-分布式OSGi

 

    默认情况下,OSGi服务只在发布该服务的OSGI容器内可见和可访问。分布式OSGi允许在一个容器内定义服务,而在另一个容器内使用这个服务(甚至是不同的机器)。

    本教程我们使用CXF的子工程DOSGi,它参考实现了OSGi Remote Service Admin 规范,OSGi 4.2企业级规范第122

github上有示例。

1 示例介绍

    遵循该教程的实践性,我们以一个示例开始,这个示例几分钟就可以搞定,然后我们再解释细节。

    我们的例子是来自教程第一部分的tasklist。唯一不同的是我们现在将modelpersisence service部署到容器A,将modelUI部署到容器B,两个容器都安装dosgi运行时。


    由于分布式OSGi不应该让所有的服务都处于active,因此规范定义服务属性"osgi.remote.interfaces"触发DOSGi是否应该处理这个服务。它希望接口的名字应该表明这个服务是输出到远端的。将属性设置为"*"则意味着服务实现的所有的接口都应该被导出。tasklist persistence service已经设置该属性,因此是默认导出的。

2 安装服务

    为了简化,我们在同一个系统中安装容器A和容器B

  1. 下载Apache Karaf 4.0.4
  2. karaf解压到文件夹container_a
  3. 启动bin/karaf

  安装服务

config:property-set -porg.apache.cxf.dosgi.discovery.zookeeperzookeeper.port 2181

config:property-set -porg.apache.cxf.dosgi.discovery.zookeeper.serverclientPort 2181

feature:repo-addcxf-dosgi 1.7.0

feature:installcxf-dosgi-discovery-distributed cxf-dosgi-zookeeper-server

feature:repo-add mvn:net.lr.tasklist/tasklist-features/1.0.0-SNAPSHOT/xml

feature:install example-tasklist-persistence

执行了这些命令行之后,tasklist持久化服务应该已经运行起来,并发布到了zookeeper

zookeeper发布包目录启动zookeeper客户服zkCli.sh,你可以检查导出的服务的wsdl: http://localhost:8181/cxf/net/lr/tasklist/model/TaskService?wsdl可以选择性检查osgi路径下的服务节点。

3 安装UI

  • 解压到container_b
  • 启动bin/karaf

 

安装客户端

config:property-set -p org.ops4j.pax.web org.osgi.service.http.port 8182

config:property-set -p org.apache.cxf.dosgi.discovery.zookeeper zookeeper.port 2181

feature:repo-add cxf-dosgi 1.7.0

feature:install cxf-dosgi-discovery-distributed

feature:repo-add mvn:net.lr.tasklist/tasklist-features/1.0.0-SNAPSHOT/xml

feature:install example-tasklist-ui

 

Tasklist客户端UI应该处于Active/Created状态,servlet可以通过 http://localhost:8182/tasklist访问。如果ui bundle处于宽限期状态graceperiod,那么DOSGi不会提供持久化服务的本地代理。

4 它是如何工作的

 

dosgi_in_details

远程服务管理(Remote Service Admin)规范定义了OSGi服务模块的扩展。当发布OSGi服务时,使用特殊的属性可以告诉DOSGi运行时导出一个可以被远程消费的服务。CXF DOSGi运行时会监听所有部署在本地容器的服务。它只处理那些具有"osgi.remote.interfaces"属性的服务。如果找到了这个属性,那么就会以它命名的接口导出或者以它实现的所有接口的名字导出。导出的方式可以使用CXF DOSGi配置选项进行调整。

默认情况下,服务将会使用CXF servlet进行导出。服务的URL来源于接口的名字。Servlet前缀、主机名、端口号默认为"cxf"、主机的IP地址和8181端口。所有的这些选项都可以使用配置管理服务(config admin)定义(参见配置选项)。默认情况下,服务使用CXF的简单前端和Aegis Databinding。如果服务接口使用JAX-RS @WebService进行注解,那么默认使用的是JAX-WS前端和JAXB databinding

服务信息也是使用DOSGi传递机制进行传播。在例子中,我们使用Zookeeper 发现实现。所以服务的元数据被写入到zookeeper服务器。

container_b会监视本地容器需要的服务。它会检查是否我们需要的服务已经存在发现的实现中(我们的例子中是在zookeeper服务器)。对于每一个它找到的服务,它都会创建一个本地代理,扮演一个实现了请求接口的OSGi服务的角色。传入的请求会被序列化,并发送到远程服务端点。

所以这将允许几乎完全透明的服务调用。开发者只需要使用OSGi服务模型,仍然可以通过容器边界进行通信。


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐