系统开发到了一定程度的时候,我发现以往有很多可以再优化的地方,于是试图去优化,最终虽然优化了,但是因为牵连的东西有点多,所以花了不少时间。经过一番思考,才意识到需要优化的不是那些代码,而是那些架构。我们需要的大系统应该由多个相对独立的小系统组成,将业务分而治之。于是就去找合适的方法来达到这个目的,很幸运的是,我发现了OSGI。
刚开始, 就只是知道 OSGI是一个实现模块化的架构,而且最初是作为一个嵌入式的java应用架构规范发展起来的,网上传得最有名的就是在BMW上的车载系统和Eclipse IDE这个两个应用。BMW没钱买来了解,只好看看Eclipse吧
。
想当年,我也尝试用eclipse来开发java程序,但嫌eclipse用起来太繁杂,用了几天,就没兴趣了,就转用比较简单,容易上手的Netbeans来做开发的IDE(也正是为了和其他习惯用eclipse的同事能合作好点,所以也就用上Maven,这是题外话了)。回过头来看Eclipse,依然是感觉超多的Plugins,弄的眼花缭乱。以前一直觉得Eclipse本身的开发也太复杂了吧,这么多的功能,得要多强大的全局观念才能兼顾得过来呀。知道有OSGI这回事后,才理解到,原来Eclipse并不需要多强的全局观念,它的功能都被“分而治之”了,这不正是我们的系统所追求的架构吗?于是,豁然开朗,但是这么多的令人眼花缭乱的功能还是令我静不下心来了解eclipse。
于是,继续找,后来在apache上找到了felix,感觉挺清爽的,并且在felix.apache.org上了解到了很多OSGI方面的一些知识,再后来就看到了karaf,有了karaf,准备运行时环境就轻松了,于是就开始尝试去开发OSGI的bundle,然后放到karaf上跑。
刚开始尝试做OSGI bundle,首先意识到的是如何组建一个bundle工程,想到既然一直以来都是用Maven做项目工程的,还是继续用Maven吧,再说OSGI Bundle在打包方面和JAR唯一的区别就是manifest.mf而已,而manifest.mf也是jar本来就有的东西,在OSGI bundle来说,只是内容上多加了几个小项而已。于是继续沿用原来的一套,拿个maven-jar-plugin插件在pom.xml里维护manifest项。
接着就是尝试编码,直接写个BundleActivator的实现了,实现start和stop方法,只是往里面写个System.out.println Balabala...。mvn package生成一个bundle。扔到<karaf-root>/deploy文件夹下,运行<karaf-root>/bin/karaf.bat或<karaf-root>/bin/karaf.sh,console出现Balabala......。尝试着stop/start bundle,看着不断Balabala...。
之后,就尝试一个bundle A在manifest.mf里export package,然后另一个bundle B在manifest.mf里import package,然后写代码用bundle A中的类创建个实例,并调用方法。扔karaf里运行之,还正常。尝试不同次序地stop/start这两个bundle,
接着就尝试在Activator的start方法里,用BundleContext的registerService发布一个OSGI Service。也正常,在karaf console里用命令ls <bundle-id>,可以列出发布出来的服务。
再接着尝试在另一个bundle里的Activator的start方法里,用BundleContext的getServiceReference方法引用刚才那个OSGI Service。也正常,可以引用并调用服务方法。
So far so good!
尝试不同次序地stop/start这两个bundle,问题出现了:服务引用那里会有返回null的情况,噩梦开始了。
由于bundle启动的次序不确定,发布service的bundle可能会比引用service的bundle启动得晚。就会出现引用的服务为null。
刚开始,我是通过在引用service的bundle的manifest里,添加import package来依赖发布service的bundle,这样当发布者未active时,引用者就不会resolved,所以,就曲线式决定了bundle的启动先后。但这是个坏实践。
后来就采用ServiceListener或ServiceTracker的方式来引用服务,这样,服务就不再依赖bundle的启动次序了。但还有个致命的缺点----要写大量的代码。
于是开始找DI的解决方案,刚开始选择了Declarative Service(DS),在felix项目下,有Service Component Runtime(SCR)的bundle可以支持Declarative Service,在manifest里用Service-Component项指定一个DS的XML文档,这个文档描述了服务及其组装关系。当bundle启动后,SCR bundle就读取该XML文档,解析并按文档组装起应用,如果某些服务未可用的话,就会延后到服务可用时再完成组装。这个过程完全由SCR bundle来管理。我们就不需要写ServiceListener或ServiceTracker来组装应用了,节省了大量的精力。
再后来,又发现了更好的Blueprint的DI方案,于是就转向用Blueprint来取代Declarative Service,实现应用的组装。
到此为止,系统还只是在单一个平台上运作,而我做的系统偏偏是由几个系统来组成的分布式的系统,于是继续找分布式的解决方案,于是又尝试ROSGI(这个开源项目已没有继续维护更新了)、接着CXF DOSGI,CXF DOSGI是可用,但发布的singlebundle版本太大(什么依赖都集成进去了),multiplebundle版本要剪裁,还存在一些和我自己用的某些bundle的版本冲突问题(这个也令我意识到import和export package时指定版本号及bundle版本管理的重要性,以后有空再聊聊这个问题)。所以cxf dosgi用了一段时间后,决定采用消息中间件来负责分布式系统间通讯的架构。
在cxf dosgi里,osgi service可以跨framework地互相调用,但服务对应的API bundle就需要在关联的系统中各运行一个。采用消息中间件后,就不需要在不同的系统间共享API了,消息所在的队列、主题及消息本身的消息头,甚至消息体都隐式地定义了API,再加上消息的异步和同步的机制,使消息中间件的应用进一步增强了每个子系统的内聚,使子系统间的耦合更加松散。
很“巧合”的是,Apache有个Servicemix的顶级开源项目,这个Servicemix和karaf的渊源十分深厚----karaf就是servicemix项目的内核独立分离出来的一个开源项目,所以,将所有以前开发的bundle移植到servicemix上,不费吹灰之力。Servicemix集成了ActiveMQ,于是Servicemix就成了我用来实现用消息中间件取代cxf dosgi方式的首选。
上了Servicemix,自然就会用上了它集成的Camel,Camel强大的企业集成能力,将系统提升到面向服务的ESB层面了。
既然上了SOA的贼船,就要想想将业务的规则和流程提炼出来,借助规则引擎或工作流引擎来实现,这是一条分支,暂时放下,日后再提。
继续OSGI方面,在camel的支持下,无状态的服务纷纷被提炼出来,成为全系统通用的服务,而这些服务可以由众多细粒度的osgi服务来组装而成。服务采用消息处理器的方式实现,在对外的接口方面,则借助ESB来实现,要什么接口,就用什么Camel Component,这些Component都是现成的。至于消息路由,还是用那个用惯了的Blueprint吧:在Camel的命名空间(http://camel.apache.org/schema/blueprint)直接在CamelContext节点中定义消息路由。
无状态的服务好解决,那么业务逻辑相关的有状态的部分怎么办呢?除了刚才提到的用规则引擎和工作流引擎外,Camel的消息处理器可以负责这部分的工作,具体的细节怎么做?我还要学习学习。
讲了这么多,似乎还没有涉及到企业应用方面的东西,例如:持久化、事务(包括分布式事务)、Web等等。但还是暂时打住,分支太多了,这条裹脚(国脚)布也够长了。
分享到:
相关推荐
- **7.1 关于OSGI**: 对OSGI的整体介绍和发展历程。 - **7.2 OSGI R4规范** - **7.2.1 Core Framework**: 核心框架的基础概念和组成部分。 - **7.2.2 StartLevelService**: 控制Bundle启动级别的服务。 - **7.2.3...
这个例子可能涵盖了支付处理系统的发展历程,涉及到模块化的演变,以及如何使用OSGi来管理和部署各个组件。读者可以通过研究这个案例,学习如何在自己的项目中实现类似的模块化结构,并利用OSGi来增强系统的灵活性和...
#### Eclipse概述与发展历程 Eclipse作为一个开放源代码的、基于Java的可扩展开发平台,自诞生以来便备受瞩目。它最初由IBM开发,2001年正式发布为开源项目。Eclipse不仅是一个简单的开发环境,更是一个强大的框架...
Eclipse 的发展历程见证了其从默默无闻到广受欢迎的转变,这得益于其不断进化的特性和开放源码的策略,吸引了诸如 IBM、Borland、Oracle 等大公司的参与。 **Eclipse 的体系结构** Eclipse 的核心设计理念是“一切...
#### Eclipse概述及发展历程 Eclipse,这一全球瞩目的开源集成开发环境(IDE),自其诞生以来便迅速成为了软件开发领域的明星。起初,作为IBM VisualAge的继任者,Eclipse旨在解决前代产品存在的扩展性差、底层技术...
2. Liferay的架构:深入探讨Liferay的技术架构,包括它是如何利用各种Java技术和框架,如Spring、Hibernate、OSGi等来构建一个灵活、可扩展的平台。 3. Liferay开发环境搭建:书籍可能会提供关于如何搭建Liferay...
2. Java的发展历程包括JDK1.1至1.6(6.0)版本,其中1.2版本后分为J2SE、J2ME和J2EE,分别针对桌面应用、嵌入式应用和企业级应用。 3. J2SE是Java程序的基础环境,J2ME用于嵌入式设备,如手机,J2EE则服务于分布式...
RCP为富客户端应用程序提供了新的解决方案,通过OSGi(开放服务网关倡议)平台运行时实现了动态插件管理,解决了部署和维护的问题。3.x版本的关键特性包括: 1. 组件化:Eclipse插件模型允许应用由多个独立的组件...
对于Java开发者,了解各个版本的J2SE(如JDK 1.1.x到J2SE 5.0)及其发布日期是非常重要的,这有助于理解语言的发展历程和不同版本间的特性差异。 在职业规划中,持续学习新技术和工具,提高在数据库管理、Web服务器...
JShell是一个交互式的Java shell工具,允许开发者在命令行中即时编写和测试代码片段,这对于快速原型设计和学习非常有用。 通过回顾Java的发展历程以及详细介绍Java 9的新特性,我们可以看出Java语言一直在不断...