浅识OSGI

OSGI

OSGI Service Platform规范提供了开放和通用的架构,使得服务提供商、开发人员、软件提供商、网关操作者和设备提供商以统一的方式开发、部署和管理服务。 OSGI通过提供灵活的服务部署机制和强大的管理功能增强了设备的智能性。OSGI规范制定的目标是为机顶盒、服务网关、Cable Modems、PC、汽车、手机等等提供服务。

OSGI是一个灵活而不失严谨的架构,是组件级复用的解决方案。OSGI为动态扩充、修改系统功能和改变系统行为提供了支撑。从技术角度方面,OSGI带来了规范化 的模块组织以及统一的开发方式 ,这为传统的模块的组织、模块开发以及模块积累提供了一种全新的指导 以及支撑。(标准的力量

OSGi中具体实现Module的单位是bundle,一个bundle就是一个jar文件,其中包含所需的类文件和资源文件,同时必须包含一个描述文件;每个bundle都可以被独立打包、部署。

模块的复用和扩展则是公司希望通过项目形成的积累,避免重复的投入

传统的方法:整个系统一个项目&每个模块一个项目的组织方式(OSGI在后者上增加了模块间的依赖关系管理和包的可见性共享管理,同时提供了相应的ClassLoader ?)

在 采用整个系统一个工程,通过包名来区分模块的方式自然使得模块的复用变得特别的复杂,在每个模块一个工程的方式则可以让模块的复用比较的简单,由于模块的 组织通常来说和系统的基础架构有直接的关联,而由于系统的基础架构没有形成规范,这样就导致有可能因为模块的组织方式不同而无法复用的现象。

OSGI在C/S和嵌入式应用开发中非常适用。

Modle

单从形式上来看,它们的确非常相似,而且它们的区别主要在于(bundle 介于 应用和package之间? ):
1)J2EE的WAR文件的粒度很大,是以应用为单位的;而OSGi bundle的粒度则相对小很多,以一组服务为单位,一个OSGi应用将包含多个bundle。 

2)最重要的差别是 ,bundle之间可以通过共享java package、发布或者引用服务进行协作。而Web应用之间几乎是不存在协作的,起码在定义上没有。

3)在J2EE中,可以将多个war文件打包成为一个ear文件进行部署,而OSGi/bundle则没有这种"Application"的概念,每个bundle都必须独立部署。

Life Cycle

bundle拥有自己的生命周期,可以被安装、启动、激活、停止等,这一点与J2EE中的WAR也非常相似。不过由于不存在协作关系,WAR的生命周期相对简单,只关心自己能否启动则可。而bundle在被激活之前,必须保证其依赖的其他bundle已经存在。

Class Loading

在J2EE Servlet规范中,对ClassLoader的着墨不多,不过目前各产品的实现都比较类似,就是每个WAR文件有一个独立的ClassLoader。 如下图,由于WebApp1和WebApp2使用不同的ClassLoader,因此它们可以使用同一个Java Class的不同版本:

Java代码
  1. +-----------------------------+  
  2. |         Bootstrap           |  
  3. |             |               |  
  4. |          System             |  
  5. |             |               |  
  6. |          Common             |  
  7. |         /      /            |  
  8. |     Catalina  Shared        |  
  9. |               /    /        |  
  10. |          WebApp1  WebApp2   |  
  11. +-----------------------------+  
+-----------------------------+
| Bootstrap |
| | |
| System |
| | |
| Common |
| / / |
| Catalina Shared |
| / / |
| WebApp1 WebApp2 |
+-----------------------------+

(from http://tomcat.apache.org/tomcat-4.1-doc/class-loader-howto.html

在这张图中我们可以看到Catalina用独立的ClassLoader,这是一个进步。早期很多人都遇到过这样的问题,自己的应用中采用了某个 开源软件,部署的时候却无法正常运行。其原因是服务器已经采用了该开源软件的较老版本,而自己的应用却依赖与新版本。新版本的Tomcat则把自己依赖的 类库放在Catalina分支,这样这些类库对所有WebApp都不可见。同时由Shared负责的类库则是所有WebApp都能够用到。

这样的ClassLoader结构对于WebApp来说已经相当不错,但是仍然有一个问题没有解决,那就是如果WebApp1需要用到 WebApp2的类怎么办?对于WebApp来说,这种需求的确相当罕见,因为应用与应用之间一般不会出现之间的类引用。但是对于一个应用中的多个模块, 相互引用则是再正常不过了。

论坛上正好有个帖子“有关于classloader的思考(或者说是困惑) ”整理了这方面的需求,我则无需重复。楼主edge_hh的问题用OSGi则可以很简单解决:
1. 在模块A的配置文件说明"Export-Package: demo.a.httpservice"
2. 在模块B的配置文件说明"Import-Package: demo.a.httpservice"
3. 将所有httpservice接口需要的定义放置在模块A的demo.a.httpservice下

这样就可以了。这就是OSGi的特别之处,bundle的CloassLoader是平级的,但平级的CloassLoader之间可以共享 Java Package。包共享还提供了过滤机制可以通过版本,供应商等信息对包进行更准确的引用。通过的包中的类进行过滤,还可以做到类级别的共享和引用。

加载机制:(每个bundle中的类,由这个bundle自己的ClassLoader进行加载)
如 果属于java.*则直接交给父加载器加载;如属于Bundle Import package中的类,则交给export package的Bundle的classloader进行加载,如加载失败,则直接抛出NoClassDefFoundException,如加载成功 则直接返回。这步就解释了之前在注意事项中所写的需要注意的包的问题。如不属于Bundle Import package中的类,则搜索是否属于Require Bundles中export的package的类,如属于则交由export package的Bundle的Classloader进行加载,如加载成功则直接返回,如加载失败则进入下一步。

服务注册

本 来Bundles可通过传统的class共享方式来实现协作,但在动态的安装和卸载代码的环境下这种方法是不适用的。服务注册为Bundles间共享 Objects提供了一种可用的模型,OSGI提供了一堆的事件来通知服务的使用者关于服务的注册和卸载,服务其实就是简单的Java objects。很多服务象objects一样,例如http server,而有些服务则代表了现实世界中的对象,例如蓝牙手机。

DS(Declarative Services)
提出了完整的Service-Oriented Component Mode(lSOCM)概念,使得在Bundle中可以按照Component+Service的方式进行开发,来看看在DS的支撑下怎么去做。

假设需要把org.riawork.opendoc.osgi.DemoComponent类定义为DS中的Component,首先需要编写一个xml文件来声明,xml文件格式类似如下:
<?xml version="1.0"encoding="UTF-8"?>
<component name="osgi.DemoComponent">
<implementation class="org.riawork.opendoc.osgi.DemoComponent"/>

 

OSGI与Eclipse

Eclipse 原本插件体系结构是一个基于XML 的静态扩展结构,即扩展(Extension)(Extension Point) ,不知道当初基于什么样的考虑,Eclipse 组织在3.0 版本选择OSGi 作为插件体系的内核,这样由OSGi 负责插件体系架构中ClassLoading 机制,由扩展与扩展点负责业务层面的扩展架构,这是一个很完美的结合。

OSIGI的好处

1)规范的、可积累的模块(标准的力量
因为没有统一的规范的基础架构体系的定义,往往每个项目、每个产品都会因为架构师的偏好、技术的发展而导致模块的开发方式完全不同。

2)可动态改变行为的系统、可插拔的系统。
服务具体由哪个模块提供,模块的安装、启动、停止、卸载,这些都可以在运行时指定,并且随时更改。这样的情况下,应用的动态性就取决于你的想象力了。举一个实在的例子,我们无需重新启动整个应用,就能够对应用进行打补丁、升级。 OSGi在面向组件的架构设计上,是一个巨大的进步。有了bundle为基础的模块结构,这使得对于企业的SOA模型更加容易设计和编写,而在项目实施部署方面更是进步巨大。再也不用为SOA应用间的启动加载依赖烦恼了。

3 稳定、高效的系统
基于OSGI的系统不会受到运行在其中的Bundle的影响,不会因为Bundle的崩溃而导致整个系统的崩溃。

实战

Bundle


Bundle 其实就是一个jar文件,这个jar文件和普通的jar文件唯一不同的地方就是Meta-inf目录下的MANIFEST.MF文件的内容,关于 Bundle的所有信息都在MANIFEST.MF中进行描述。Bundle通过实现BundleActivator接口去控制其生命周期,在 Activator中编写Bundle启动、停止时所需要进行的工作,同时也可以在Activator中发布或者监听框架的事件状态信息,以根据框架的运 行状态做出相应的调整。Bundle是个独立的概念,在OSGI框架中对于每个Bundle采用的是独立的classloader机制,这也就意味着不能 采用传统的如引用其他Bundle的工程来实现Bundle间的协作了,那么在OSGI框架中Bundle之间是怎么协作的呢,在OSGI框架中对于每个 Bundle可定义输出的包以及引用的包,这样在Bundle间就可以共享包中的类了,尽管这样也可以直接实现简单的Bundle的协作,但在OSGI框 架中更加推荐的是采用Service的方式。每个
Bundle可以通过BundleContext注册对外提供的服务,同时也可以通过 BundleContext来获得需要引用的服务,采用Service-Oriented的方式可以使得对外提供的服务能够更加的封闭,不需要为了使用别 的Bundle提供的Service而做环境依赖等的设置,同时,Bundle还可以采用Require-Bundle的方式来直接引用其他的 Bundle(相当于引用其他Bundle的工程或jar)

Service

在OSGI框架中,Service是个实际的概念,只有通过BundleContext注册成Service才 能使得一个POJO作为Service在OSGI框架中被使用,同时也只有通过BundleContext 来获取发布到框架中的Service,通过Service的方式来实现Bundle之间实例级的依赖, 和Import-Package、Require-Bundle不同的地方在于通过Service获取的是其他Bundle 中类的实例。
我们需要在Bundle启动的时候注册需要发布的Service,在Bundle停止的时候卸载发布的Service,在OSGI框架中通过调用BundleContext来注册Service ,方法是这样的:
context.registerService(服务标识名,服务实例,服务实例属性);
方法返回的是ServiceRegistration,可以通过返回的这个ServiceRegistration来卸载这个Service,在stop方法中通过这样的方法来卸载注册的这个Service
serviceRegistration.unregister();
在OSGI框架中通过这样的方法来获取服务:
ServiceReference serviceRef=context.getServiceReference(服务标识名);
Object service=context.getService(serviceRef);
可以通过stop命令来停止另外两个Bundle的运行:
stop 11

部署OSGI应用

1 安装OSGI内核(可以是Equinox )
2 把所需要的所有bundle(自己开发的和依赖的lib ),放在budle目录
3 在根目录中部署配置文件config.ini
在Demo目录下建立configuration目录,在其中放入config.ini文件

osgi.noShutdown=true
#当前系统下运行的Bundle,可以在此指定Bundle的启动顺序
osgi.bundles=reference/:file/:bundles/ConfigFileValidatorBundle_1.0.0.jar@start,ref
erence/:file/:bundles/DBValidatorBundle_1.0.0.jar@start,reference/:file/:bundles/LD
APValidatorBundle_1.0.0.jar@start,reference/:file/:bundles/org.eclipse.equinox.http
_1.0.0.v20060601a.jar@start,reference/:file/:bundles/org.eclipse.equinox.servlet.api
_1.0.0.v20060601.jar@start,reference/:file/:bundles/org.eclipse.osgi.services_3.1.10
0.v20060511.jar@start,reference/:file/:bundles/UserValidatorBundle_1.0.0.jar@start,
reference/:file/:bundles/UserValidatorWebBundle_1.0.0.jar@start
osgi.bundles.defaultStartLevel=4


4 通过ant或maven把上面的部署自动化(应该花些时间来好好学习一下ant和maven

运行时通过ss、start、stop、install等命令对bundle进行管理。

Equinox基于OSGI的扩展

Extension Registry

Extension Registry是Eclipse插件机制中关键的部分,它为插件的扩展提供了一种实现的机制,Bundle通过发布扩展点的方式来定义Bundle可扩 展的部分,当需要扩展Bundle的时候只需要实现Bundle提供的扩展点的接口就可以了,通过这样的方式就可以完成Bundle的扩展了。(Service和Service.share之间就是使用的这种方式

 
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值