锁定老帖子 主题:OSGi的热部署特性及实现
精华帖 (0) :: 良好帖 (0) :: 新手帖 (2) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-04-04
最后修改:2009-04-05
很多文章里都提到了OSGi的热部署特性,但是很少有实例去演示它。
所谓热部署,就是在不停止服务运行时(或者说在不影响用户体验前提下)动态更新其服务内容,最终达到100%在线率的目标。而Java中,由于类加载机制的原因,导致一个类一旦加载进去就再也无法释放,因此,OSGi引入了基于插件的类加载机制,举例说明:plugin1里有examples.Test1类,而pulgin2里也有examples.Test1类,在载入这两个插件时,两个类是可以同时载入进入到类缓存中,这归功于OSGi实现的插件类加载器(ClassLoader),具体大家可以查看BlueDavy的《OSGi实战》和《OSGi进阶》两本电子书,我就不在这里费口舌了。
OSGi中,实现热部署最关键的方式就是使用服务 (Service),例如,我们要注册一个服务: // 代码1 // BundleContext context ... context.registerService("examples.Test", "world", null); 这样,就注册了名称为“examples.Test”,值为“world”的服务,其他依赖的插件们,只需要使用下面代码即可以调用: // 代码2 // BundleContext context ... Object rtn = context.getService(context.getServiceReference("examples.Test")); 好了,这些都是基础部分,下面看看如何来实现热部署的。
假设,我有一个插件为 examples_1.0.0,表示为 examples 插件且版本为1.0.0版,它里面使用【代码1】注册服务之后,其他依赖的插件们使用【代码2】调用“examples.Test”服务后返回的是“world”。经过一段时间运行后,运营人员发现“examples.Test”服务的值应该是“hello”,而不是“world”,这个bug就被找出。因此,开发人员就更新了 examples 插件,并升级版本为 1.0.1,代码内容改变如下: // 代码3 // BundleContext context ... context.registerService("examples.Test", "hello", null); 使用OSGi运行环境安装了 examples_1.0.1 插件之后,根据热部署的概念,按道理说依赖的插件们使用【代码2】调用的结果应该是“hello”才对,有一些OSGi实现确实是这么做的,但是一些主流的实现(如 equinox 等)返回的其实还是原来“world”,这是为什么呢?
这其实是 Service Ranking 搞的鬼,默认情况下,每个服务的 Service Ranking 都为 0(零),因此,在注册同名服务时,默认加载第一个注册的服务。因此,为了让依赖的插件们加载最新的 examples_1.0.1 插件所提供的服务,我们需要把【代码3】进行如下修改: // 代码4 // BundleContext context ... Dictionary props = new Dictionary(); props.put(org.osgi.framework.Constants.SERVICE_RANKING, new Integer(100)); context.registerService("examples.Test", "hello", props); 我们把“examples.Test”服务的 Service Ranking 属性更改成了 100(任何比所有其他服务的Service Ranking都大的值) 之后,该服务的排名就会排到最前面,依赖 examples 的插件们再使用【代码3】调用服务后,就返回了我们想要的“hello”字符串。
这也就是说,在不需要停止服务和其他插件都不用更新的情况下,我们只需要再安装一个更新版本的插件,其所注册的服务就可以自动更新并应用到所有调用该插件的插件中,达到了热部署的目的。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-04-05
最后修改:2009-04-05
感觉不太对,热部署应该是指把在系统启动后,在OSGi环境里管理bundle吧?service应该属于bundle的一部分,可以这样分开来操作么?
或许是没有了解lz的意思,不过我们用最简陋的方法,为bundle配置activator,在bundle安装的时候自动把service注册上。 |
|
返回顶楼 | |
发表时间:2009-04-06
xyz20003 写道 感觉不太对,热部署应该是指把在系统启动后,在OSGi环境里管理bundle吧?service应该属于bundle的一部分,可以这样分开来操作么? 或许是没有了解lz的意思,不过我们用最简陋的方法,为bundle配置activator,在bundle安装的时候自动把service注册上。 我说的就是你表达的这个“最简陋”的方法呀,呵呵。 所有的代码都是在插件的 BundleActivator.start 方法里实现的,而且所有Bundles也都是OSGi环境里管理的,这是规范,必须要遵守。 我的目的是想用一个非常简单的案例来描述在OSGi环境下热部署的特性,毕竟很多人都知道OSGi好,但不知道其到底好在哪里。 |
|
返回顶楼 | |
发表时间:2009-04-28
最后修改:2009-04-28
osgi的思想很好,在开发的过程中或多或少都会按照服务划分模块;确实osgi感觉开发的时候不方便(没有maven方便),现在使用像maven这些包依赖管理工具,已经很方便了,而且osgi的热部署能力大多情况都用不上。能请lz举举你们在项目中怎么使用osgi的吗?
|
|
返回顶楼 | |
发表时间:2009-04-29
最后修改:2009-04-29
glacier3 写道
osgi的思想很好,在开发的过程中或多或少都会按照服务划分模块;确实osgi感觉开发的时候不方便(没有maven方便),现在使用像maven这些包依赖管理工具,已经很方便了,而且osgi的热部署能力大多情况都用不上。能请lz举举你们在项目中怎么使用osgi的吗?
其实,OSGi的特性之一,就是用规则去迫使架构师在软件设计上重视bundle的可重用性。假设我们开发一款游戏软件(仅仅是假设),那么,游戏端可以是这样的: 而服务器端的软件,可以是这样的: 由此,可以看出,两个软件不同之处仅仅在于 com.xiapao.games.ddz.client.jar 和 com.xiapao.games.ddz.server.jar,而其他的bundles都是公用的。
这里就有个好处,如果我们在发牌算法上,更改了一些算分策略或者出牌策略,那么,在理想情况下,游戏端会自动下载更新的bundle(s),例如更新 com.xiapao.games.ddz.jar 这个公用bundle,然后在后台进行安装,通过本文讲的热部署特性加载新策略算法。当玩家玩完一局,不用关闭软件,再开始一局时,就可以使用新的策略来进行计算了,所有的事情都在不知不觉中进行,不会影响用户体验。 |
|
返回顶楼 | |
发表时间:2009-05-22
glacier3 写道 osgi的思想很好,在开发的过程中或多或少都会按照服务划分模块;确实osgi感觉开发的时候不方便(没有maven方便),现在使用像maven这些包依赖管理工具,已经很方便了,而且osgi的热部署能力大多情况都用不上。能请lz举举你们在项目中怎么使用osgi的吗?
OSGI Bundles是最基本的单元。另外,开发OSGI Bundles时可以将maven作为工具生成相关文件。OSGI和maven是两个不同的概念。 |
|
返回顶楼 | |
发表时间:2009-06-15
这个热部署以后还要重启应用才能识别新的bundle 能否不重启应用自动识别新的bundle然后部署bundle呢?
|
|
返回顶楼 | |
发表时间:2009-06-16
大家有没有OSGi比较好的实例?我自己写过!但是还不是很熟练,有些应用不知道该从哪里下手!比如,自动搜索合适的Bundle并且安装!可以的话,请发到我的邮箱:zhouwendong006@163.com
|
|
返回顶楼 | |
发表时间:2009-06-16
shijiyu 写道 这个热部署以后还要重启应用才能识别新的bundle 能否不重启应用自动识别新的bundle然后部署bundle呢?
不用重启啊,在console里,直接install就行。 |
|
返回顶楼 | |
发表时间:2009-09-15
好处还是很多的
1 不同buddle使用自己的类加载器,解决了一些冲突问题,比如在classpath中有多个包,碰巧一个名字相同的类在两个包中都有,那么只能加载第一个 2 相对于jar包的管理,osgi提供了额外的信息,比如版本,明确的依赖关系。 3 热部署 应该还有的,呵呵 |
|
返回顶楼 | |