写点什么

OSGi 中的服务模型与扩展者模型

2013 年 11 月 26 日

在 OSGi 中,实现 bundle 间交互和扩展性有两种常见的方式,也就是服务模型(service model)和扩展者模型(extender model)。

服务模型较为容易理解,在这个模型中包含了服务的提供者、使用者以及注册中心。服务接口构成了提供者和使用者之间的契约,提供者将希望别人调用的服务发布到注册中心,使用者到注册中心查找符合需求的服务。在传统的服务模型中,都是通过查找的方式使用服务,但是随着 Declarative Service 以及 Blueprint 的流行,服务可以在运行时注入,简化了开发人员的编码过程。

图 1:OSGi 中的服务模型(图片来源于《OSGi 实战》)

扩展者模式更为灵活和抽象,它是与 OSGi 的生命周期相关联的。在《OSGi 实战》一书中是这样描述扩展者模式的:扩展者模式背后的主要思想是,在其他bundle 的生命周期事件(安装、解析、启动、停止等)上构建动态扩展性。通常,应用中的某个bundle 扮演扩展者的角色:它负责监听bundle 的启动、停止。当一个bundle 启动时,扩展者会对其进行检测并判断它是否是一个扩展bundle。扩展者检查bundle 的清单文件(使用bundle.getHeaders())或bundle 的内容(使用bundle.getEntry()),以此来寻找它能够识别的特定元数据。如果这个bundle 确实包含一个扩展,那么该扩展会通过元数据来描述。扩展者读取元数据并执行必要的任务,这有助于将扩展bundle 集成到应用中。如果扩展bundle 被停止,扩展者同样会监听到,此时扩展者会将相关的扩展从应用中移除。(《OSGi 实战》一书由人民邮电出版社翻译出版,对应的文字来源于第89 页)。在Eclipse 插件开发中最常用的扩展点模型就是一种典型的扩展者模式,不过这是Equinox 的特有实现,并不是OSGi 规范的一部分。

图2:《OSGi 实战》一书中图形样例所对应的扩展者模式

近日,针对这两种模型的优劣和使用场景,有人阅读在完 Apache Felix 样例文档后产生了疑问,并在Stackoverflow 进行了咨询。OSGi 领域中的资深专家、 Bndtools 作者 Neil Bartlett 对此进行了细致的回复,而 OSGi 联盟技术总监 Peter Kriens 更是专门撰写博文来解释这一问题。

Neil Bartlett 认为服务更为常用,应该作为第一选择,除非有明确的理由才要设计新的扩展者。扩展者模式更为灵活和抽象,但是理解和使用起来会更加复杂。他以在 OSGi 应用中实现帮助系统作为例子,其他的 bundle 只需在约定的目录下包含一个 HTML 文档,核心的帮助系统 bundle 会扫描这些 bundle 以查找 HTML 文档并将其添加到主页的帮助索引中。这个特性如果使用服务来实现的话就会比较繁琐:假设遵循“白板(whiteboard)”模式,你需要定义一个带有 getHelpDocuments() 方法的 HelpProvider 接口,任何想提供帮助内容的 bundle 都需要实现这个接口并将其注册为服务。而如果采用扩展者模式的话会更加简便,因为能够跟踪到 bundle 的到来和消失。在现实世界中,扩展者模型用到了如下的地方:

  • Declarative Services 是一个扩展者,它会查找其他 bundle 中的 Service-Component 声明,并且会执行初始化组件、注入服务等操作。
  • Blueprint 也是一个扩展者,所做的事情很类似,它会查找 Bundle-Blueprint 声明或约定路径下的 XML 文件。
  • OSGi 企业级规范所定义的 JPA 扩展者会查找 Meta-Persistence 头信息中所声明的 persistence.xml。如果找到的话,将会为该 bundle 创建持久化单元。
  • Eclipse 也包含了扩展者(所起的名字有点令人感到迷惑,叫做 Extension Registry)。Eclipse 使用它来创建视图、透视图以及菜单等,它们通过位于 bundle 根目录中的 plugin.xml 文件进行声明。

总而言之,服务用来基于契约注册和查找对象,而扩展者用来扩展 bundle 的功能,通常会基于某种类型的资源声明或头信息,而不是可执行的代码。

Christian Schneider 是 Talend 的开源软件开发人员,主要工作内容包括 Apache Camel、Apache Karaf 以及 Apache CXF,针对这个问题,他的看法是扩展者主要用于框架之中,它需要了解 bundle 的内部实现,因此不利于松耦合,但是其优势在于能够定义全新的抽象功能,如 Blueprint、Declarative Services 以及 CDI,这些框架都是使用扩展者模型将 bundle 按照一定的规范装配在一起的。而服务对于应用本身来说是正确的选择,它能够隐藏实现的细节,同时能够避免服务的使用者实例化类,因此有利于实现松耦合。在实际中,我们经常会组合使用它们,如可以使用 CDI 注解来装配服务,在内部 CDI 会使用扩展者模型,而对于应用本身来说则使用服务来将 bundle 装配在一起。

在 Peter Kriens 的博文中,他将bundle、服务以及扩展者类比为日常的社会交流。在社会交流场景中,我们会扮演不同的角色,如商业交易中的销售方和购买方。在OSGi 中,µservice 模型就是这样的参与者。µservice 比其他的服务模型更适合这样的场景,因为它是基于动态化的。

在社会化的类比中,bundle 就是具体的人,它会控制行为并选择要参与什么样的场景,以及要使用或提供什么样的服务。但是有一些场景是重复性的、无聊的并且不是我们主要的兴趣所在,这时候使用服务就不太合适了。假设我有两辆汽车,其中一辆在探测到我有车钥匙时会自动打开车门,而另一辆做不到这一点,因此我会更喜欢前一辆。

我们可以使用OSGi 模拟这样的场景,因为能够知道已经安装了什么bundle 以及何时有新的bundle 安装进来。就像那辆聪明的汽车能够探测到我口袋中的钥匙一样,bundle 也可以查看其他bundle 中的内容并作出相应的反应。Peter 还讨论了数据库迁移的例子,同样使用了扩展者模式。数据库模式的扩展者bundle 会根据其他bundle 的模式描述文件,对数据库作出相应的变更,这样的话,一些凌乱的代码就能统一抽取到扩展者bundle 中了,另一个类似的例子是在Declarative Services 的实现中,会有一个专门的扩展者bundle 来负责解析XML、处理依赖等繁琐的事情。Paremus 的packager packs 也使用这种模式来统一管理应用的生命周期。

那么究竟该何时使用服务模式,何时使用扩展者模式呢?

Peter 认为,服务模型是关于 bundle 中核心领域内容的,它应该是 bundle 中主要的关注点所在,代码应该按照这种模式来进行编写。扩展者模式主要用来将杂乱和样板式的代码从领域 bundle 转移到一个特定的 bundle 之中。了解服务和 bundle 的动态性会极大地帮助我们理解这两种模型。

服务和扩展者都是在 OSGi 中十分重要和常见的模型,希望本篇文章中介绍的专家观点能够帮助您厘清它们的概念以及适用场景。

2013 年 11 月 26 日 07:342007

评论

发布
暂无评论
发现更多内容

面试官:Java性能调优你会多少?一个问题就把我问的哑口无言,哭了!

996小迁

架构 Java性能调优 Java性能调优面试

与前端训练营的日子 -- Week16

SamGo

学习笔记

APM 行业认知系列 - 八 - DevOps 的25个优点

东风微鸣

DevOps APM Trace 可观察性

备受开发者青睐的“Spring全家桶”(双重理念)技术实战与面试结合

Java成神之路

Java 程序员 架构 面试 编程语言

环信助力中国游戏社交类APP出“东南亚”记!

环信

Supercell还香嘛?

李小腾

腾讯 中台 阿里 Supercell

APM 行业认知系列 - 五

东风微鸣

APM Trace 可观察性

APM 行业认知系列 - 七 - 定义 DevOps 的17种方式

东风微鸣

DevOps APM Trace 可观察性

APM 行业认知系列 - 九

东风微鸣

DevOps APM Trace 可观察性

APM 行业认知系列 - 二

东风微鸣

APM Trace 可观察性

MySQL事务浅析|由浅入深

云流

MySQL 编程 架构

干货来袭!阿里大佬“亲码”Java全线笔记,差距不止一点点

程序员小毕

Java 程序员 面试 分布式 微服务

如何 0 改造,让单体/微服务应用成为Serverless Application

阿里巴巴云原生

Docker Serverless 容器 微服务 云原生

APM(应用性能监控) 行业认知系列 - 一

东风微鸣

APM Trace 可观察性

APM 行业认知系列 - 三

东风微鸣

APM Trace 可观察性

面试磕磕碰碰,辛得蚂蚁高级工程师的技术笔记指导,终获P7岗offer

Java成神之路

Java 程序员 架构 面试 编程语言

APM 行业认知系列 - 四

东风微鸣

APM Trace 可观察性

技术资讯 | BML CodeLab发布重磅更新!!

百度开发者中心

AI 工具软件 #百度#

新CEO帕特·基辛格回归 英特尔或将上演创新的“速度与激情”?

新闻科技资讯

APM 行业认知系列 - 十 - 十一

东风微鸣

DevOps APM Trace 可观察性

你的面试专属!JVM G1GC的算法+实现,90张图+33段代码

Java架构追梦

Java 架构 JVM 调优 G1GC

滚雪球学 Python 番外系列,自动化测试是个啥?

梦想橡皮擦

Python 28天写作 2月春节不断更

神级!字节2-4大牛出品:分布式技术笔记,让你在分布式的路上如履平地!

Java架构之路

Java 程序员 架构 面试 编程语言

阿里P8技术官带你玩转Spring全家桶,从Spring到Boot到MVC在到Cloud微服务实战

Java成神之路

Java 程序员 架构 面试 编程语言

Angular性能优化实践——巧用第三方组件和懒加载技术

Geek_Willie

angular SpreadJS

2020回顾,2021学习目标

叫练

学习 2021年展望 2020年度总结

某某大龄程序员被字节面试官怒喷“废物”,他得知真相之后都懵了

Java架构之路

Java 程序员 架构 面试 编程语言

APM 行业认知系列 - 六

东风微鸣

APM Trace 可观察性

2021版最新!字节跳动3面+腾讯6面一次过,谈谈我的大厂面经

Java架构之路

Java 程序员 架构 面试 编程语言

我遇到的真实医疗场景信息化及患者路径

卢嘉敏

需求 分类 医疗 调研 用户

币掌柜量化交易机器人系统开发

系统开发咨询:I76-883I-5I52 邓森

低代码的认知误区与落地实践

低代码的认知误区与落地实践

OSGi中的服务模型与扩展者模型-InfoQ