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这类插件的场景相对是比较好发挥动态化的(因为插件之间的交互依赖通常不多),尤其是在新装/停止一个插件时,更新会比较麻烦一些。
osgi最明显的缺陷
- bundle尽管可以为隔离的服务建立独立生命周期管理的热部署方式,以及明确的服务导出和导入依赖能力,但是其最终基于jvm,无法对bundle对应的服务实现计算资源的隔离,一个服务的故障依然会导致整个jvm crush,这使得在一个运行时的osgi上部署模块级服务只获得了模块部署和启停隔离,服务明确依赖的好处,但是没办法实现计算节点的线性扩展,在当前分布式,微服务,网络计算的趋势下,使得osgi只适合构建单一服务节点的内部应用,但是其分离的bundle的部署负担对于微服务架构来说,有点用大炮打蚊子的臭味。
推荐的应用架构方式
- 因此必须将基于进程间构建的分布式应用和进程内的单一应用分开来架构设计,对于进程间构建的分布式应用,采取基于soa的理念进行容器模式的服务部署模式,服务交互基于远程服务交互相关协议,采用可忍受网络失败的架构设计原则;
- 对于进程内的应用,如果需要模块级的独立生命周期热部署和模块管理,可以考虑采用OSGI,但是,容器内基于本地进程间通信的模块交付方式不仅能提供同样的独立生命热部署和模块管理,而且具备随时脱离出去部署成单独容器级服务应用的能力,加速进程间的服务交付提供的整体管理和监视环境基础.
- osgi还有用武只地吗?当然我前述都是以构建分布式企业和面向互联网这类应用为前提来讨论的,对于嵌入式的jvm应用,比如著名的osgi案例宝马的车载系统,osgi依然是最好的原则,不过我怀疑基于andriod系统的机制构建类似应用,osgi的采用依然值得商榷。因此,osgi确实面临鸡肋之嫌。
分布式应用的关键技术点及解决思路汇总
- 为什么要分布
为得到吞吐量和可靠性及故障隔离的架构属性,需要将传统的单一应用按照业务逻辑进行垂直拆分以实现构建工程的独立,部署的独立。 - 分布失去了什么
- 进程内服务调用的便利性和可测试性
- 代价巨大的资源分布导致的跨资源事务能力
- 部署和运维工作量指数级增长
- 不可靠网络的应用状态一致性
- 及其复杂的分布式应用依赖关系
- 分布式关键技术选择
- 容器级的分布式应用工程和部署管理;
- 可视化的分布式应用及服务监视管理视图;
- 前端和后端应用的分离;
- 客户端路由
- 服务注册中心
- 分布式协调
- 消息中件间
- 分布式存储
- 集成框架
OSGi 的核心配置、动态化及问题的更多相关文章
- PHP的核心配置详解
1.PHP核心配置详解 代码在不同的环境下执行的结果也会大有不同,可能就因为一个配置问题,导致一个非常高危的漏洞能够利用:也可能你已经找到的一个漏洞就因为你的配置问题,导致你鼓捣很久都无法构造成功的漏 ...
- kafka系列七、kafka核心配置
一.producer核心配置 1.acks :发送应答(默认值:1) 生产者在考虑完成请求之前要求leader收到的确认的数量.这控制了发送的记录的持久性.允许以下设置: acks=0:设置为0,则生 ...
- dubbo系列五、dubbo核心配置
一.配置文件 1.生产者配置provider.xml <?xml version="1.0" encoding="UTF-8"?> <bean ...
- 006-spring cloud gateway-GatewayAutoConfiguration核心配置-GatewayProperties初始化加载、Route初始化加载
一.GatewayProperties 1.1.在GatewayAutoConfiguration中加载 在Spring-Cloud-Gateway初始化时,同时GatewayAutoConfigur ...
- hibernate核心配置
# hibernate核心配置 注意: - hibernate.cfg.xml默认放在src目录下(这样可以自动加载该文件) - 必须配置的参数: * 数据库的四大参数和方言 - 可选配置的参 ...
- JavaWeb框架_Struts2_(二)----->Struts2的核心配置
2. Struts2的核心配置 2.1 配置Struts.xml文件 2.1.1 Struts.xml文件 Struts2框架的核心配置文件是Struts.xml,该文件主要用来配置Action和 ...
- Hibernate的核心配置
Hibernate的设计思路 Hibernate是一种全自动化管理持久化对象的ORM框架,既提供了完全面向对象的封装完整的对象持久化接口(屏蔽db层的差异化,提升代码可移植性),也提供了操作HQL和S ...
- MyBatis 核心配置综述之Executor
目录 MyBatis四大组件之 Executor执行器 Executor的继承结构 Executor创建过程以及源码分析 Executor接口的主要方法 Executor 的现实抽象 上一篇我们对Sq ...
- Atlassian In Action-Jira之核心配置(二)
道生一,一生二,二生三,三生万物. --<道德经> 如果说第一节的指导思想是管理之"道",那我们本节的核心配置就是Jira系统之"道"了.有了核心配 ...
随机推荐
- php中常用的运算符
运算符 运算符是告诉PHP做相关运算的标识符号. PHP运算符一般分为算术运算符.赋值运算符.比较运算符.三元运算符.逻辑运算符.字符串连接运算符.错误控制运算符. 1.变量名记得加“$” 符: 2. ...
- 找第k大的数
(找第k大的数) 给定一个长度为1,000,000的无序正整数序列,以及另一个数n(1<=n<=1000000),接下来以类似快速排序的方法找到序列中第n大的数(关于第n大的数:例如序列{ ...
- Date and Time
The PHP date() function is used to format date and/or a time and formats as timestamp to a more read ...
- iOS常用正则表达式验证(手机号、密码格式、身份证号等)
#import @interfaceUtils : NSObject #pragma 正则匹配手机号 + (BOOL)checkTelNumber:(NSString*) telNumber; #pr ...
- context理解
官方文档的解释是:Context提供了关于应用环境全局信息的接口.它是一个抽象类,它的执行被Android系统所提供.它允许获取以应用为特征的资源和类型.同时启动应用级的操作,如启动Activity, ...
- Android SoundPool.play方法的音量与系统音量的关系
Android中播放音频,除了使用MediaPlayer,还可以使用SoundPool.SoundPool使用音效池的概念来管理多个短促的音效,对于需要短促的提示音的场景特别合适. 通常调用Sound ...
- Unity3D ShaderLab 模拟纹理运动
Unity3D ShaderLab 模拟纹理运动 这一篇,我们要说到着色器上的uv贴图的滚动效果,这样的场景可以用在河流,瀑布,熔岩等效果.算是创建纹理动画的基础技术之一. 所以 准备一个新的着色器文 ...
- dos快速通道
要在文件夹的右键菜单中添加“命令提示符”选项.在注册表HKEY_CLASSES_ROOT\Directory\shell分支下新建一项“CommandPrompt”,修改右侧窗格中的“默认”键值为“命 ...
- Word Ladder II
Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...
- How to adjust OOM score for a process?
转载自http://www.dbasquare.com/kb/how-to-adjust-oom-score-for-a-process/ How to adjust OOM score for a ...