让 OSGi 服务使用最新版本的 bundle,即使安装了多个 bundle 版本

Posted

技术标签:

【中文标题】让 OSGi 服务使用最新版本的 bundle,即使安装了多个 bundle 版本【英文标题】:Having OSGi services use latest version of bundle, even if multiple bundle versions are installed 【发布时间】:2021-09-13 20:48:45 【问题描述】:

我正面临一个 OSGi 问题,而且我对 OSGi 细节的了解还不够,无法找出前进的方向。

我的问题是这样的:

我有一个服务,它位于定义良好的接口之后,并定期在特定位置发出文件。这由配置管理员控制(通过 Karaf 中的配置文件) 某些组件通过 Karaf 功能文件向其他组件提供此服务,将我的服务捆绑在特定版本 (1.X.0) 中 其他组件在较新的版本(1.Y.0,其中 Y > X)中提供此服务,或者通过另一个功能文件,或者只是将其添加到他们的 kar 文件中。

由于这些只是较小的版本更改,因此消费服务并不真正关心它们与哪个服务通信(API 相同)。

我的问题是这两个包都在 karaf 中处于活动状态,并且存在关于谁可以覆盖谁的输出文件的竞争条件。 我尝试将@Component 变成一个单例(使用scope = ServiceScope.SINGLETON),虽然这可能会解决每个服务使用者使用相同实现的情况,但文件覆盖问题仍然存在,因为两个服务都处于活动状态。

基本上,我正在寻找一种方法来告诉 OSGi“不要打扰旧版本,新版本(与其他版本相同)适用于所有消费者(使用默认为[1.X,2[)

由于配置文件类似于启用我的服务的“API”,因此我希望避免为不同版本设置多个配置文件。

如果可能,我希望将版本位置逻辑保留在我的服务之外。我想从理论上讲,该服务可以侦听提供相同服务接口的其他版本的捆绑包,并采取适当的措施——但这对我来说似乎很麻烦。肯定有更好的方法,对业务逻辑代码(即我的服务)影响更小?

【问题讨论】:

【参考方案1】:

简单的答案当然是,为什么要打扰旧捆绑包?直接卸载?

无论如何,通常的答案是:出于某种原因,我不能。一些首选(我的)顺序的解决方案:

    删除旧捆绑包 将您的组件require 配置为配置并配置适当的组件,另一个将无法运行。这基本上是为我们提供了配置器规范的模式。这实际上是我在任何地方都使用的真正很好的解决方案。它允许对应用程序进行详细配置。 只需解决bundle中的配置文件冲突即可。 使用 startlevels 从不启动较旧的捆绑包。有点小技巧。 向服务注册服务属性并让引用过滤该属性。兔子洞。 使用服务挂钩过滤掉旧服务。这引入了排序,因为必须在任何人使用它之前注册服务挂钩。所以我倾向于回避它。这是implementation

恕我直言,这是一个典型的用例,回想起来,它使系统比预期的要复杂得多。像这样的一个黑客似乎并不算太​​糟糕,但这些黑客往往像兔子一样繁殖。 OSGi 是关于与定义良好的服务通信的干净模块。你的描述似乎你在那里,但没有正确解决问题会导致你再次走上大泥球的道路:-(

【讨论】:

【参考方案2】:

对于 Apache Karaf,有一种特殊的方法可以实现 Peter 的第一个解决方案(删除旧包)。

在提供服务的捆绑包的功能文件中设置dependency=true。 这样 Apache Karaf 将自动安装最佳的 bundle 以满足您其他 bundle 的要求。在这种情况下,它应该只安装具有最高次要版本号的提供包。

【讨论】:

以上是关于让 OSGi 服务使用最新版本的 bundle,即使安装了多个 bundle 版本的主要内容,如果未能解决你的问题,请参考以下文章

OSGI依赖问题处理

OSGi HTTP Bundle - 绑定到两个端口

osgi + felix example3编写与使用服务的改进

osgi + felix example2b编写

我为啥不在osgi中使用spring

Java Web应用集成OSGI