OSGi 包更新如何工作?

Posted

技术标签:

【中文标题】OSGi 包更新如何工作?【英文标题】:How does OSGi bundle update work? 【发布时间】:2011-05-18 20:55:36 【问题描述】:

当一个包被更新(比如修复一个错误)时,当前正在使用正在更新的包的其他包会发生什么?

说有两个bundles service和dao。当我发出命令更新 dao 层时,假设服务包中的类正在使用 dao 包中的类。使用dao代码的服务层中的类会出现异常吗?


感谢您的response。

我的意思是用相同的版本更新。

直到发生包含依赖包的包刷新。

更新包的用户会调用包刷新操作,对吗?说当用户调用refresh来更新dao bundle时,bundle服务中的一个类调用了dao层中一个类的方法……这种情况会发生什么?

我发现这篇博文很有帮助: http://solutionsfit.com/blog/2008/08/27/osgi-what-modularity-can-do-for-you-part-1/

来自帖子:

如果我们简单地用包含修复的包替换包,容器将注销旧包并注册新包。然后代理可以处理引用改组并恢复服务调用。这种交互几乎是瞬间的。您的客户将完全不知道发生了什么,而您刚刚为公司节省了大量资金(我听到奖金了吗?)。

在这篇博文中,对 authorizePayment() 的调用被暂停,直到更新的捆绑包可用。如果在 bundle 刷新发生时控件在 authorizePayment() 方法中会发生什么?

【问题讨论】:

【参考方案1】:

Bundle 有两种依赖:

服务和 之间的连接 类加载器,由包键入 名字。这些连接称为 电线。

服务很容易撤回,因为这是其设计所固有的。电线更难,因为它们错综复杂地编织在你的物体中,而这些物体不知道动态。所以当你安装一个新的包时,旧的包保持原样,你的对象没有更新,更新的包仍然像僵尸一样提供它的电线。

当您调用 refreshPackages 时,框架会查看这些依赖项并找到引用这些僵尸程序的包。然后停止每个僵尸。捆绑包的约定是它应该清理。我们通过为您进行大量清理来帮助捆绑包,但有些事情非常糟糕,例如将引用存储在其他包的静态中或忘记停止已启动的线程。以其他方式依赖于这些捆绑包的其他捆绑包会收到捆绑包停止的通知,因此它们也可以清理任何引用。捆绑包停止后,捆绑包未解析,然后针对新捆绑包再次解析。

对于真正的 OSGi 包,清理是自然的,并且在您的代码中并不真正可见(应该如此)。它得到了声明式服务、iPOJO、依赖管理器、Spring、蓝图等工具的良好支持。神奇之处在于专注于 µservices 模型,而不是 dong 类加载技巧。

为什么我们不自动刷新?好吧,我们曾经做过,但令人耳目一新是破坏性的。在许多情况下,您需要更新多个捆绑包。每次更新后出现这种中断将是不必要的痛苦。也就是说,在安装或更新之后,您应该始终进行刷新,但您可以将多个安装/更新括起来。

【讨论】:

【参考方案2】:

当您使用 OSGi 'update' 命令更新包时,很可能有其他依赖包依赖于它并且已经捕获了一个集合从这个包的旧版本加载的类。通常符合您在问题中描述的问题的情况。

为了避免这个包所包含的不同版本的类之间可能出现的不一致,OSGi 容器决定暂时对外界隐藏更新包的类的新版本。您可以将其视为将更新的类与其他包隔离的一种方式-暂时-。

这里的重点是 OSGi 容器不能仅仅从目标包的新版本开始加载类,因为依赖包最终会看到它们已经加载的类的旧版本,与新版本的更新后加载的相同类,这将包含会导致无法控制的混乱的不一致。捆绑卸载也是如此,捆绑从已安装的捆绑列表中删除,但不会从内存中删除。应该保留它,以便依赖包可以继续从中加载类。

因此,您可以将“更新”命令视为引入同一捆绑包的新版本,提供给尚未到来的依赖捆绑包 - 尚未出现在更新时-。虽然旧版本 - 在更新之前存在 - 保留在内存中,以确保向后兼容性并避免对已经开始依赖于更新包的现有包造成任何可能的中断。

请注意,旧版本仅保存在内存中,这意味着重新启动服务器将导致清除所有这些旧版本并将最新版本带到桌面上。这很有意义,因为不需要向后兼容,只是因为所有捆绑包现在都在同一时间开始..

接下来会发生什么,您必须在特定捆绑包上显式调用“刷新”命令,这些捆绑包依赖于更新的捆绑包,或者改为您可以选择运行“刷新”命令而不指定特定的捆绑包,这意味着所有捆绑包都将被盲目刷新。 'refresh' 命令强制重建目标包的依赖树,并强制它们的类加载器从头开始加载所需的类。

只有这样,依赖包才会开始看到您对已更新的包中的类的代码所做的更改。

规则是

已经导入旧版本类的现有已解析捆绑包不会自动重新连接到新捆绑包,除非它们被刷新。

【讨论】:

【参考方案3】:

更新捆绑包时,会安装新的修订版(捆绑包的位)。如果另一个捆绑包连接到更新捆绑包的先前修订版,即另一个捆绑包导入了先前修订版导出的某个包,或者另一个捆绑包需要之前修订版的捆绑包,那么 OSGi 框架将保留更新的捆绑包的先前修订版bundle 为来自依赖包的未来类加载请求提供服务,直到发生包含依赖包的包刷新。

这样做的目的是在更新依赖项时最小化或延迟干扰依赖包。管理代理可能想要更新多个捆绑包,并在最后执行捆绑包刷新以“现代化”依赖关系。包刷新完成后,更新包的先前修订版没有任何关联,OSGi 框架现在可以随意丢弃先前的修订版。

因此,在您的示例中,通常不会导致异常。但当然,这取决于相关代码实际在做什么以及它们的捆绑清单是如何编写的。

【讨论】:

以上是关于OSGi 包更新如何工作?的主要内容,如果未能解决你的问题,请参考以下文章

jdo/OSGi:捆绑更新后构建 JDO PersistenceManagerFactory 时出错

Jetty 更新到 9.4.x 后:缺少约束:Require-Capability: osgi.extender;过滤器:=“(osgi.extender=osgi.serviceloader.pro

OSGI 和 JSF 如何协同工作?

osgi 安全模型是如何工作的?

如何使用 EclipseLink 使 PostgreSQL 与 OSGi 一起工作

高效的 OSGi 开发工作流程