场景
单机应用已经越来越不能符合目前越来越复杂的产品需求了。即使是小型应用,至少也需要部署2台以上的服务器做集群。且应用必须24小时对外服务,可用性得达到n个9。这就对发布有了更高的要求。
也就催生了灰度发布这样的发布过程。而即使是这样,还是需要经历大致如下的发布过程:
- 下载代码
- 打包
- 停止服务器
- 部署
- 启动服务器
而业界一直诟病JVM的启动速度,再加上如果项目比较大,编译过程比较长,发布机器比较多,那么做一次完整的发布可能需要几个小时。万一中途出了问题,要回退,又要几个小时。
是否可以解决这样的问题呢?而OSGi恰是一个不错的选择!
OSGi
OSGi是一个优雅、完整和动态的组件模型,提供了完整的模块化运行环境。
应用程序(称为bundle)无需重新引导可以被远程安装、启动、升级和卸载。
其主要应用在嵌入式开发中,而在JavaSE和JavaEE方面则少有建树。其最著名的使用就是eclipse了。究其原因主要有:
- 增加开发难度:需要开发人员更关心模块的划分,处理模块与模块之间的依赖关系(模块间的导入导出),这是一个好的方面,但是
- 没有完善的工具:模块间的依赖关系需要开发人员手动处理(有相应的工具,但不能百分百处理依赖关系)。
- 额外的运行环境:应用(bundle)需要运行在实现了OSGi规范的容器内,导致了模块间的依赖关系需要在运行时才能验证是否有问题。也就是说无法在编译期验证模块间的关系。同时也增加了测试及调试的难度。
可以看出,OSGi的主要缺点是开发较繁琐。而针对前面所提到的问题,OSGi解决了如下几个问题:
- 项目模块化,对于项目的更新与发布不再需要发布整个项目,只需要发布需要更新的模块即可。提高了编译打包的速度。
- OSGi可在运行时的对bundle进行安装、启动、升级和卸载。提高了部署的速度。(这里就需要吐槽一下eclipse了,它是基于osgi的,但是每次安装插件都要重启是要搞哪样?!)
- 支持多版本发布。在OSGi容器内可发布相同应用的不同版本
OSGi是如何做到这些的呢?其实OSGi实现了一套自身的ClassLoader,具体可见此文
OSGi容器
目前OSGi容器主要有Knopflerfish, Apache Felix, Equinox, Spring DM。其具体比较请见此文
以及其上的一些应用,方便在OSGi上进行开发,比如Karaf,ServiceMix等。
OSGi的使用方式
OSGi容器有两种使用方式:
作为容器使用:
OSGi容器作为外层,所有的应用均部署在OSGi容器内。那么所有的应用都需要bundle化,但是上面说了,bundle化不是一个方便的过程。 且OSGi在非嵌入式领域并不是很流行,虽然之前业界一直在推广,但最终效果并不理想,Spring最后也放弃了对OGSi的支持。 所以当你的应用较大时,bundle化会是一个比较大的绊脚石。
嵌入式使用
基于上面的原因,我们可以将OSGi容器作为嵌入式容器使用,即基本的模块在OSGi外部运行,也就不需要bundle化了, 变动比较频繁的模块部署到OSGi容器内,使用OSGi便利的部署机制。 比如:项目中依赖的Spring,Mybatis等jar包可以在OSGi容器外部署,而业务模块则部署到OSGi容器内
Felix安装
这里使用felix作为OSGi容器来演示嵌入式OSGi的使用!felix可到Apache网站下载!
felix目录结构如下:
-bin:felix.jar路径,其实felix只需要这个jar包就可以运行了
-bundle:部署的bundle目录,如果你有需要部署的bundle,将其拷贝到此目录下,启动felix时会自动部署
-cache:bundle缓存目录
-conf:配置文件目录
-doc:相关文档
在根目录运行如下命令即可启动
java -jar bin/felix.jar
- bundle目录下默认有四个bundle,提供了类似命令行功能。启动时自动部署了。可以输入lb,来查看已安装的bundle
g! lb
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (5.4.0)|5.4.0
1|Active | 1|Apache Felix Bundle Repository (2.0.6)|2.0.6
2|Active | 1|Apache Felix Gogo Command (0.16.0)|0.16.0
3|Active | 1|Apache Felix Gogo Runtime (0.16.2)|0.16.2
4|Active | 1|Apache Felix Gogo Shell (0.10.0)|0.10.0
g!
这是普通的使用felix的方式。不做过多介绍。主要介绍嵌入式Felix的应用。
嵌入启动Felix
创建Maven项目
- 首先创建一个普通的Maven项目
- 在pom.xml中添加felix依赖
<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.main</artifactId>
<version>5.4.0</version>
</dependency>
</dependencies<