说说OSGi

我其实有好几年没摸过OSGi了,但也许是因为我以前写过的那些OSGi的文章,还有在2009年的时候我把公司的一个基础产品换成了基于OSGi,于是每年还是有不少外部的人或内部公司的人问我关于OSGi的各种问题,尤其是在某些场景是不是需要选择OSGi的问题,在这里简单说说我的观点和理由吧。

先说下2009年当时我把那个基础产品改造成基于OSGi的原因,当时这个基础产品面临两个问题:
1. 和应用的jar依赖冲突的问题
这个基础产品本身也依赖了不少jar,而应用方依赖的jar就更多了,因此经常会出现基础产品依赖的jar和应用依赖的jar版本冲突的问题,如果基础产品只是提供给少数几个应用用还好办,而这个基础产品是提供给上百个应用用的,不太可能说出现冲突就去解决,而且其实也没法解决,例如A应用要依赖hessian 3.x,B应用要依赖hessian 4.x,那对基础产品来说就悲催了。
因此希望能和应用的依赖隔离开,避免这种冲突问题。

2. 版本升级的问题
当时这个基础产品在线上分布的版本已经有较多个了,而推进应用方升级是一个漫长的过程,因此当时想如果能动态的去升就好了。

基于这两个需求,再加上我自己一直希望能用上OSGi,于是就决定把这个基础产品改造为基于OSGi,当时改造的时候我先交给了一个同事去做这件事,状况就是在折腾了一个多月后,进展仍然是非常的缓慢,于是我就自己来折腾了,我自认当时的自己对OSGi还是比较熟的,结果还是折腾了很久,我大概也花了一个月的时间,才终于改造好,直到完成这个基础产品的改造,对OSGi我才终于有了更多的理解。

在改造这个基础产品时,我看到的使用OSGi的问题是:
1. 对没有接触过OSGi的Java开发而言开发习惯绝对是巨大的挑战
通常都会使用Maven来管理Java工程,肯定很希望mvn eclipse:clean eclipse:eclipse就可以生成导进eclipse里没问题的project吧,但对于OSGi而言,如果是依赖外部的非OSGi Bundle的jar,那么则需要在META-INF/MANIFEST.MF里写明,也就是不是仅仅修改pom.xml就可以的;另外一点是OSGi对于其他bundle的jar的依赖,不是通过pom.xml去增加依赖,而是直接import package或require-bundle之类的,并且要求这个bundle是已经安装了的(可以想象,如果是业务型的应用,那得装多少bundle…),否则在eclipse之类的ide里再去import什么的时候会找不到,同时为了确保mvn clean package之类的还是能用,因此会被逼在开发的时候要同时维护pom、MANIFEST.MF。
上面的这两个问题要解决好,可以通过开发IDE插件,但这个插件是不太好做的…
而OSGi的classloader机制则会给初入门的带来很多疑惑,会觉得经常碰到各种各样的class找不到等问题。
测试也是个麻烦,因为得把所有的bundle都装进framework,否则单元测试就得全部靠mock了。
另外一点在文件的依赖上就更折腾了,OSGi只能是通过require-bundle来去获取需要依赖的文件,否则是做不了的。

2. 动态化
OSGi确实具备了很强的动态化机制,但这里的要求是必须对OSGi bundle/OSGi Declarative Services的生命周期管理机制非常清楚,否则设计出来的系统其实是完全不可动态化的,具体的细节大家可以看看我之前写的另外一篇文章

而仅仅借助OSGi的动态化机制,其实是不足以实现真正的热部署的,这里的一个原因是通常代码里是带状态信息的,或者说一些全局变量信息,而OSGi的替换其实主要是通过创建新对象实例,然后替换引用的方式来实现,这也就意味着对于有状态信息的,得自己处理好状态的保存以及还原,否则是会有问题的,我们当年为了在通信层面做到这点,折腾了一个多月还是没搞定,而且系统变得超级复杂。

另外还有个更麻烦的是,如果应用是OSGi和非OSGi混用,又要做动态化,那就得让非OSGi拿到的只是一个OSGi里对象的一个假的引用,以便随时替换,这个改造起来就更麻烦了。

当年那个基础产品改造完后,确实享受到了和应用隔离带来的好处,动态化在生产环境也玩过下,确实挺爽,但付出的代价是极大的,并且要做到真正的完全动态是不行的,也就意味着动态化这特性基本就是个玩具,因此后来在回顾这次技术决定时,我一直都承认,这是我做的一个最技术的,最失败的决定,如果是可以重来,我会选择不用OSGi,而是自己做一个简单的classloader隔离机制。

所以在那之后,当其他人问我是否可以在一些场景选择OSGi时,我给的建议都是:
如果你的场景不是对动态化(并且是无状态的那种动态化)有强烈的需求,那不要选OSGi。
仅仅是为了模块化,隔离这些,还不如自己做一个简单的实现,并且可以遵守现在的开发习惯,不要去挑战众多人的开发习惯和通用的知识体系,那对系统维护来说绝对会是一个灾难,只能说或许等到将来Java从语言级支持了可能才OK。

至于为什么众多的AS(例如Weblogic、JBoss)这些会选择基于OSGi,我觉得有一点很重要的是在没有选OSGi之前,他们对外提供的(销售的)版本是打包性质的,不能由用户来选择,这显然对销售会有限制,而如果能提供插件样的选择,则是一件好事,另外一个选择的原因很有可能是他们认为OSGi会成为语言级的标准,那意义就比较大了,不过可惜从目前来看,这估计不太可能。

至于众多人爱的eclipse,为什么选用OSGi,很大程度是看中了OSGi的动态化,以及减少了自己制定一个插件标准的折腾,eclipse这类插件的场景相对是比较好发挥动态化的(因为插件之间的交互依赖通常不多),尤其是在新装/停止一个插件时,更新会比较麻烦一些。

ps: 作为一个eclipse党,最近连续被伤害了两次,两次都是因为在eclipse remote debug直接导致remote jvm crash,而idea则一切正常,有人碰过类似的问题吗?现在正在逐步的切换为idea党。

=============================
欢迎关注微信公众号:hellojavacases

关于此微信号:
分享Java问题排查的Case、Java业界的动态和新技术、Java的一些小知识点Test,以及和大家一起讨论一些Java问题或场景,这里只有Java细节的分享,没有大道理、大架构和大框架。

公众号上发布的消息都存放在http://hellojava.info上。

《说说OSGi》有4个想法

  1. 当年还在支付宝时,还在纳闷为什么程立首架搞sofa的时候为什么只是部分的借用了OSGi的思想和框架,看了您的这篇文章,才知道那是经过深思熟虑的。:)

  2. OSGi经过几年的发展,目前已相当成熟了,例:JIRA、HUDSON、http://osgi.jxtech.net 都是OSGI企业级开发的典范。

kaidi进行回复 取消回复

电子邮件地址不会被公开。 必填项已用*标注


*