Karaf教程第8部分-分布式OSGi
默认情况下,OSGi服务只在发布该服务的OSGI容器内可见和可访问。分布式OSGi允许在一个容器内定义服务,而在另一个容器内使用这个服务(甚至是不同的机器)。
本教程我们使用CXF的子工程DOSGi,它参考实现了OSGi Remote Service Admin 规范,OSGi 4.2企业级规范第122章)
github上有示例。
1 示例介绍
遵循该教程的实践性,我们以一个示例开始,这个示例几分钟就可以搞定,然后我们再解释细节。
我们的例子是来自教程第一部分的tasklist。唯一不同的是我们现在将model和persisence service部署到容器A,将model和UI部署到容器B,两个容器都安装dosgi运行时。
由于分布式OSGi不应该让所有的服务都处于active,因此规范定义服务属性"osgi.remote.interfaces"触发DOSGi是否应该处理这个服务。它希望接口的名字应该表明这个服务是输出到远端的。将属性设置为"*"则意味着服务实现的所有的接口都应该被导出。tasklist persistence service已经设置该属性,因此是默认导出的。
2 安装服务
为了简化,我们在同一个系统中安装容器A和容器B。
- 下载Apache Karaf 4.0.4
- 将karaf解压到文件夹container_a
- 启动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 它是如何工作的
远程服务管理(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服务模型,仍然可以通过容器边界进行通信。