基于OSGi的企业级开发框架实践——序篇
OSGi就好比达摩克利斯之剑一般,在其强大而锋利的背后却隐藏着让人窒息的危险。我的形容好像有点夸张,不过在现实中大多数的研发团队基本上都认为OSGi并非像各类评论文章中介绍的那样光彩熠熠,而更多的像是食之无味,弃之可惜的鸡肋。诚然,我不能强迫每个人都接受我的观点,在每个项目中始终不渝的实践OSGi。但是做为一项已经存在了10年以上的成熟技术,为什么会被如此的抵触而未被广泛的应用,这确实是我应该去探究其原因的。
从OSGi的出身我们不难发现,其应用领域最初是针对嵌入式设备的,OSGi的全称为:Open Service Gateway Initiative,最初的目的是为各种嵌入式设备提供通用的软件运行平台。当然随着技术的不断进步和演变,Java平台的不断完善,OSGi技术也被运用到了其他的研发领域,比如Eclipse IDE。
J2EE和OSGi的结合似乎也是理所当然的事情,然而越是看上去合乎情理的事情,却越是前途坎坷。由于OSGi本身的一些特性导致其在J2EE企业级开发领域尤其是在WEB研发领域存在着一些先天的不足。这里先来讲一个故事(这里的故事可不是Scrum中的user story,哈哈):在我参与的一个系统项目中,做为架构师,我毫不犹豫的选择了OSGi作为系统的技术底层框架并用一些听起来非常令人信服的理由说服了项目组的其他干系人(我承认我的选择不是百分之百的正确,你可以认为我是青春期的冲动),但是问题很快的来到了,我们的UI设计师在调试WEB模块中的JSP页面时发现了问题——由于OSGi的资源管理特性,导致每次JSP页面上的修改都要重启WEB模块,而不是像之前在SSH框架中的那样所改即所见(也无需重启Servlet容器)。很快UI设计师就开始抱怨,为什么修改一个简单的HTML标签都要执行一次重启命令,这将令UI设计师的工作效率大大降低。做为架构师的我当然要负这个责任,因为是我的“固执”导致了问题的发生,我应该为这个问题所造成的损失而买单。我面临的选择是:要么放弃OSGi重新回到SSH上,要么找到解决问题的方法。由于项目已经进行到了中途,放弃将是代价昂贵的,所以我选择了寻找问题的解决方法。经过不懈的努力最后终于证实问题的根源是OSGi中Bundle的生命周期特性所导致,当Web Bundle启动时事先会加载所有的JSP页面资源。所以在运行时修改的JSP页面并不会立即反映到已加载到OSGi容器中并处于激活状态的bundle中,必须要重启该bundle才能重新加载修改后的JSP资源。解决这个问题就是要解决如何的动态加载JSP资源,这就涉及到要侵入bundle的生命周期。最后由于UI设计师的强烈抵制以及项目进度的制约,我并没有采用修改Bundle生命周期的方案,而是采用另外一种更加重型的折中方案(该方案实现比较简单快速),以此缓解UI设计师的愤愤不平(最终UI设计师又重新回到了她所熟悉的SSH下的工作方式)。不过正是因为采用了这种重型的折中方案,使我发现了OSGi在企业级开发架构中另外一种UI和后端服务分离的新思路,正所谓塞翁失马,焉知祸福。这个事例只是我在OSGi项目中遇到的一个非常小的问题,之后又遇到了许多各式各样的奇怪问题,最终所有问题都得到了圆满的解决,但是这也证实了,为什么会有那么多的研发团队在项目调研之初会信誓旦旦的宣称将使用OSGi来实现项目,而到了实际实施中又不得不放弃的窘境。的确OSGi在企业级研发中存在着诸多的问题,这也是我为什么要写这篇冗长文章的原因,我将通过我的实践经验,来为大家介绍一套行之有效的基于OSGi的企业级开发框架!
纵观当今天下,我唯一比较熟悉的最成熟而且是比较早运用OSGi技术的组织莫过于alipay了(当然也有其他的一些银行研发团队在实践)。不过alipay的OSGi是一种伪OSGi,因为他们系统中的所有bundle并不是真正的classloader级别的隔离,而只是Spring上下文的隔离,即一个bundle一个ApplicationContext。而不是一个bundle一个classloader并且一个ApplicationContext。所以我称之为伪OSGi。虽然alipay的SOFA是一个伪OSGi的运行时开发框架,但现实中的一切都证明了它是成功的(挺过了各种类型的大促,例如双11等等)。SOFA本身也会不断的自我成长,会变得更加的完善和可靠。这里我不是在推销alipay的SOFA框架,只是想证明一点,OSGi是适合J2EE企业级开发的,关键是如何的用好它——这把达摩克利斯之剑!
我个人认为,要成为一款优秀的OSGi开发框架应该具备如下要素,才能称之为OSGi Framework:
1.开发框架必须为开发者提供所有的基础设施,而且不能与应用程序的业务逻辑产生耦合;
2.开发框架必须提供一套代码模板,减少开发人员的代码量,让开发人员将关注点集中于业务逻辑模型的设计;
3.开发框架必须提供一套助手或是工具,避免开发人员重复造轮子;
4.开发框架必须提供一套有效的集成测试工具,简化开发人员的测试工作;
5.开发框架必须提供一套自动化的打包部署方案,简化应用程序的发布和部署;
6.开发框架必须被设计成高扩展性,方便开发人员的个性化扩展;
7.开发框架必须被设计成高可靠性和高维护性,能够方便开发人员排查错误,至少是报的错误能让开发人员看懂;
8.开发框架必须提供翔实的开发手册,帮助开发人员快速的熟悉了解框架的运行机制和组织结构;
当然,还有一些我尚未想到的要素,希望读者可以补充之。
好吧,序篇就写到这里吧。我是一个纯粹的实用主义者,不会因为时髦的前沿技术而去冒险。每当我选择一项技术前,我都会反复的问自己,这是我需要的东西的吗?如果我使用了它,它会为我带来利益吗?虽然有些事情只有通过自己的实践才会知道东西的好坏,但是并不是每一件事情都需要自己亲历亲为,因为在当今时代中,我们更需要站在巨人的肩膀上来完成我们自己的任务,这样我们会用更快的速度实现我们想要的结果。我承认我自己是很难做到这点,重复造轮子的冲动每每的让我热血沸腾,只是要证明别人能做到的,我自己也能做到而且做的更好。重复造轮子并不是坏事,只是说重复的造重复的轮子是没有意义的,但是重复的造出更好的轮子,那又何乐而不为呢?因为更好的轮子能够带领我们更好更远的前进。
下一篇是扫盲篇《OSGi与Spring DM技术分享》,引用的是2010年自己写的一篇培训文档。虽然网上已经有很多类似的文章,但是这个重复的轮子或许会让你有意想不到的收获。