论坛首页 Java企业应用论坛

讨论:关于OSGi Based 应用服务器

浏览 13218 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-04-05  
我觉得system boot环境持有的应该是bundle中的引用,而不是实际的对象。(这点只是猜想尚未去代码实现里做过验证)

从规范文档里看,OSGi的bundle也是可以指定依赖顺序的,即当环境中已经存在了某些依赖才可以安装成功,并启动服务。从spring dm那本书里可以看到支持类似的依赖检测。(这点也没实际用过,但是感觉import-package这类的含义应该就是指定bundle的前提条件)

再者,通过接口编程,system boot里获得的只是一个接口,这里很像rmi之类的远程调用,个人感觉就算bundle被uninstall了,system boot又去访问,最多就是一个ClassNotFoundException,在system boot里catch住就行了。

我们更愿意把OSGi看做是原系统的插件平台,估计跟OSGi Server的概念相差甚远,但是OSGi的热部署之类的形式应该是相似的。不过接触时日尚短,希望多多批评指正。

0 请登录后投票
   发表时间:2009-04-05  
要动态还是用动态语言吧
0 请登录后投票
   发表时间:2009-04-05  
我觉得不是动态的问题。

是模块化切分和版本管理问题。

试想,本来做产品需要一个trunk,多个branches。要是换了OSGi,产品都可以按模块算了,多少个模块,每个模块用哪个版本。

这样是不是就好多了,而且可以把interface都抽离到单独的api里,制成一个bundle,其他bundle提供实现,系统集成测试时再把各个模块拼接起来。这样是不是更好一些。
0 请登录后投票
   发表时间:2009-04-06   最后修改:2009-04-06
wl95421 写道

假设有一个Bundle称为A,可以被另外Bundle称为B的来热更新
问题是谁来负责状态更新啊?
是A吗?不应该是,因为A和B应该没有严格的约束关系?
是B吗?也不应该是,原因同上
OSGi容器吗?问题在于,谁知道哪些状态要更新,更新的方式是什么呢?可以想一下J2EE的Session,它做HotDeploy的方式也可以算是一种热更新,但我觉得目前所谓J2EE服务器所谓的HotDeploy基本是个玩具(过分一点说,可以说是笑话),而且如果更新失败,又怎么处理呢?
再比如说,现在有代码持有了Bundle A中的某个服务对象,那么怎么办呢?


假设你所说的SymbolicName为A的bundle版本为 1.0.0, 如果要更新,建议你新做一个版本为 1.0.1 的A的bundle,然后进行安装。这样,依赖关系就得以保存了。就像之前那位仁兄说的,已经调用旧版本的事务中,会继续使用旧版本的服务,而新的事务就会调用新版本的服务。待到所有的插件都调用新版本的服务后,再卸载旧的那个bundle,这不就达到了热部署的目的了么? 如果1.0.1版本的A安装出现问题,那事务们顶多还是用回1.0.0版本的服务,不用停机修复。

wl95421 写道

大家如果有兴趣的话,可以查一下JDK的历史,它曾经有一个版本,是1.1的某个版本,支持Class的Unload和Reload,结果后来又放弃了,然后给出了一个严格的Class对应的Unload和Reload规范,现在几乎不可能做到Class的Unload和Reload了。有兴趣的朋友可以查一下这段历史,有些意思的。


在JVM里要支持Class的Unload和Reload是不可行的,因为它的规范里没有版本管理这一说,所有的类所在的JVM都是同一个版本的,呵呵。而OSGi就有版本管理的机制,也就是说同一个SymbolicName的Bundles,只要版本不同,就可以并存,这也是热部署机制的基础。
0 请登录后投票
   发表时间:2009-04-06  
yipsilon 写道
leadyu 写道
如何保证新的应用实例是安全的呢?比如你的代码里存在静态数据,而这些数据是功能依赖的,在热部署后,状态丢失,新的代码还能正确跑起来吗?

当然,可以通过ClassLoader去制造一个相对隔绝的应用环境,但是也是没法完全保证所有的引用是隔绝的,同时也没有办法替换新的状态,存在诸多限制,对应用代码来说,不是完全透明的机制。不能说,中间件有热部署功能了,就可以放心的更新代码了


OSGi热部署实现原理我的文章里有介绍:http://yipsilon.iteye.com/blog/361660

OSGi规范中定义可以使用BundleContext.getAllServiceReferences方法来获取所有的同名服务,如果你的旧插件中存储有状态,使用上述方法可以获取到旧插件对象,然后新旧插件之间进行一下状态更新不就可以了。



OSGi,我倒没升入研究过,不过,起码中间件提供的热部署方案是不安全的。好,再看你说的OSGi的做法:可以得到旧的引用,更新下状态,我想到的有几个问题:

首先,就像前面那位老兄说的,你怎么知道插件里有状态需要更新?不管是Buddle A还是Buddle B去做,都不合适,由容器去做,也有问题:

旧有状态里面可能存在一些引用,而这些引用对应的类可能也被更新了,简单的付值过来可是不行的哦,如果OSGi允许获取这种旧有的对象引用,这种引用其实等同于,破坏了OSGi规范好不容易维护起来的隔绝环境
0 请登录后投票
   发表时间:2009-04-06   最后修改:2009-04-06
leadyu 写道

OSGi,我倒没升入研究过,不过,起码中间件提供的热部署方案是不安全的。好,再看你说的OSGi的做法:可以得到旧的引用,更新下状态,我想到的有几个问题:

首先,就像前面那位老兄说的,你怎么知道插件里有状态需要更新?不管是Buddle A还是Buddle B去做,都不合适,由容器去做,也有问题:

旧有状态里面可能存在一些引用,而这些引用对应的类可能也被更新了,简单的付值过来可是不行的哦,如果OSGi允许获取这种旧有的对象引用,这种引用其实等同于,破坏了OSGi规范好不容易维护起来的隔绝环境


我明白你所担心的问题了,看看下面的伪代码:
class ServiceObj{
  public String state;
}
...
// BundleA_1.0.0 中注册了一个服务
ServiceObj obj = new ServiceObj();
obj.state = "hello";
context.registerService("example.Test", obj, null);
...
// BundleB_1.0.0 中调用该服务
ServiceObj rtn = (ServiceObj)context.getService('example.Test'/*假设这是ServiceReference*/); // state 返回 hello
rtn.state = "changed"; // 这里更改了状态
...
// BundleA_1.0.1 中更新了此服务
ServiceObj obj = new ServiceObj();
obj.state = "world";
context.registerService("example.Test", obj, null); // 安装的时候更新了状态。
...
// 当BundleB_1.0.0 再次调用此服务时
Object rtn = context.getService('example.Test'/*假设这是ServiceReference*/); // 旧的状态 changed 没有了,state 返回的是最新的 world

这段代码说明服务内部状态被改变了,是这个意思吧?
0 请登录后投票
   发表时间:2009-04-06  
引用

在JVM里要支持Class的Unload和Reload是不可行的,因为它的规范里没有版本管理这一说,所有的类所在的JVM都是同一个版本的,呵呵。而OSGi就有版本管理的机制,也就是说同一个SymbolicName的Bundles,只要版本不同,就可以并存,这也是热部署机制的基础。


不是这个原因,而是关于static变量。我在书上看到的是JVM应该可以Unload一个Class,但不敢肯定JVM中是否规定,但Sun的JDK应该是遵守了这个标准。
书中说JVM如果Unload一个Class,当前Class的ParentClassLoader,假设为AClassLoader,需要满足以下条件:
1、由AClassLoader其所有加载的Class,及其实例都不能被外部引用
2、由AClassLoader其所有加载的Class,不能包含static字段

这个条件正常运行基本上是不能满足地。
所以所谓的Class Unload也基本是不可能的。

至于是否热更新,部署的问题,不想讨论了,如果谁有真正实现了的方案,再一起看看了。

0 请登录后投票
   发表时间:2009-04-06  
wl95421 写道
引用

在JVM里要支持Class的Unload和Reload是不可行的,因为它的规范里没有版本管理这一说,所有的类所在的JVM都是同一个版本的,呵呵。而OSGi就有版本管理的机制,也就是说同一个SymbolicName的Bundles,只要版本不同,就可以并存,这也是热部署机制的基础。


不是这个原因,而是关于static变量。我在书上看到的是JVM应该可以Unload一个Class,但不敢肯定JVM中是否规定,但Sun的JDK应该是遵守了这个标准。
书中说JVM如果Unload一个Class,当前Class的ParentClassLoader,假设为AClassLoader,需要满足以下条件:
1、由AClassLoader其所有加载的Class,及其实例都不能被外部引用
2、由AClassLoader其所有加载的Class,不能包含static字段

这个条件正常运行基本上是不能满足地。
所以所谓的Class Unload也基本是不可能的。

至于是否热更新,部署的问题,不想讨论了,如果谁有真正实现了的方案,再一起看看了。



JVM要UnLoad一个ClassLoader,首先,必须所有的由这个ClassLoader定义的类产生的实例全部UnLoad,而且这个过程是JVM内部的。另外一个类A调用类B时,如果类B没有被加载,那么VM会采用类A的Loader去Load类B。

再看,yipsilon上面写的代码,这是其中一个问题,但还不是最大的麻烦,比如可以通过你之前说的获取老版本的引用把属性拷贝过来。还不光光只是静态成员有问题,如果属性本身是个自定义类实例,比如是example.Test的一个实例。那么拷贝过来,也还只是老版本的一个实例,它所有的引用都会采用老版本的ClassLoader去加载,那就乱套了,

所以,基本我了解的热加载实现,似乎都不会去做状态的更新这种事,热加载后,老状态都是任由其丢失的。不管,中间件也好,Osgi也好,都是一样的思路,通过各种限定切分模块,保证组件的隔离性,来实现热加载。

不知道,JDK15的Instrucment是否安全的热加载实现?没试过

0 请登录后投票
   发表时间:2009-04-07   最后修改:2009-04-07
大体看了一下Instrument特性, 个人感觉 instrument 跟OSGi规范中的类加载机制实现目的是一样的,但对于已经new的对象也是无能为力,它可以做的也是当new新对象时,自动把class类转换过去。也就是说对于已经存在的对象,当存在状态时,也是无法进行新旧转换的。

不知道理解的是否正确...
0 请登录后投票
论坛首页 Java企业应用版

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