如何部署 OSGi 应用程序和依赖项?
Posted
技术标签:
【中文标题】如何部署 OSGi 应用程序和依赖项?【英文标题】:How to deploy OSGi apps and dependencies? 【发布时间】:2011-04-25 00:30:09 【问题描述】:通过不将数十个 JAR 依赖项包装到 lib 目录中,OSGi 似乎有一个很好的好处,即拥有小型可部署工件。但是,我找不到任何可以告诉我将依赖项部署到容器的简单、可靠的方法。例如,我有一个使用 CXF 和几个 Spring 子项目的应用程序。如果我需要将此应用程序部署到新的 Glassfish 服务器,那么确保安装所有依赖项的最佳方法是什么?
我正在使用 Maven,似乎可能有一些方法可以有一个挂钩来查看 META-INF/maven 目录并从 pom.xml 中提取依赖项列表然后去获取所需的库(可能来自本地仓库)。有没有办法做到这一点?
Pax 插件听起来像是在这样做,但它似乎是基于对 Felix 容器的增强?这不是我想要的,我正在处理一个已经在运行的远程容器。
有没有像命令行工具这样的东西而不是GUI?
【问题讨论】:
【参考方案1】:您的问题的一个基本方面尚未解决。
Glassfish 确实是一个成熟的应用服务器,就像大多数现代应用服务器一样:它们为您提供了一个 Web 容器(您可以在其中部署 WAR 档案)、一个 Java EE 容器(在 JAR 和 EAR 档案中部署 EJB),以及集成 OSGI 容器。然后后者用于应用服务器自己的内部启动机制。
实质上,您可以定位三个容器。现代 IDE 和构建工具为您提供了打包逻辑以针对其中任何一个目标的方法。所以问题就变成了:我如何在所有这些可能性中构建我的应用程序?
有一些非常重要的技术问题不容忽视。 (我在这里专注于客观和事实考虑,避免任何主观选择、哲学、策略和其他可能对您的最终决定也有很大影响的上下文相关考虑):
-
OSGI 容器不为您提供隐式或声明式 线程管理、持久性或事务管理 Web 和 Java EE 容器等服务。因此,请计划分析这些问题并生成代码来管理您的线程并处理这些线程上的事务传播。当然,OSGi 提供了所有必要的 API 来处理这些方面,但确实需要编码(AOP 可能会有所帮助)。另一方面,在 Web 和 Java EE 容器中,您依赖容器管理的服务和/或使用 EJB 注释、部署描述符和服务器管理的对象(如池)来简单地声明您想要并行的线程数、线程的大小连接池,以及哪些事务属性。两种风格都有优点和缺点(OSGi 中的过程与 java app.server 中的声明或隐式)。
OSGI 提供了一种有序的方式来加载你的代码,管理模块依赖,甚至处理多个共存版本 相同的模块,以及动态添加/删除和启动/停止所谓的 bundles(OSGI 部署单元),前提是您的 bundle 确实包含处理潜在启动的逻辑/stop 问题,例如在停止时正确中断所有启动的线程 - 线程可能已经通过其他依赖模块“传播”。另一方面,Java EE 和 Web 容器通常会装载依赖 JAR 的副本,这可能会产生更多的部署,除非您开始考虑应用程序服务器的 类加载器层次结构并利用它来部署“共享库” ' 可以是普通的 POJO JAR,也可以是打包在 JAR 中的 Java EE bean。无论如何,在后面的情况下,管理部署依赖项成为一个问题,您必须至少在构建时使用像 Maven 这样的框架来解决这个问题。然后,在运行时,您可能必须根据依赖项编写启动/停止级联脚本;否则,利用特定的应用程序服务器扩展来解决 Web 和 Java EE 容器(例如 Weblogic)中的这些动态部署问题。
如前所述,现在大多数应用服务器都使用 OSGI 来管理自己的启动顺序。随着平台复杂性的增加、API 的增加、组装单个最终产品的开发团队数量的增加以及大量第三方/开源组件的使用,OSGI 成为不可或缺的服务器启动工具,以确保所有组件的稳定版本和一组一致的兼容版本。想想 Eclipse IDE:拥有数千个插件的目录和很高的新版本发布率,如果没有 OSGI 作为基础,这个 IDE 将是一个非常脆弱的平台。现代应用服务器面临同样的问题。
基于上述考虑,您可能很想将代码分层到一些设施中,这些设施可以基于 OSGI 层,进而为 Java EE 提供核心服务bean 层托管业务逻辑,然后是一个 Web servlet 层来接口整个...但是另外两个问题弹出:(a) 你如何使所有这些组件一起通信? OSGI 有自己的存储库机制,除非在 OSGI 中明确发布,否则其他模块不会看到已部署的 JAR 的 API。 Web 和 Java EE 容器使用完全不同的存储库技术来访问彼此组件的接口,即 JNDI。同样,查看您的特定应用程序服务器文档,该文档可能提供从 OSGI 包处理 Java EE bean 的方法,反之亦然(例如 Glassfish,自 V3 以来);但要小心线程管理和事务范围。 (b) 您将如何避免干扰应用程序服务器的启动顺序? 与 Web 相比,OSGI 倾向于成为核心系统功能(在供应商的管理下)和 Java EE 容器自然 面向托管您的应用程序代码(在您的管理下)。升级您的应用服务器或安装新版本可能会干扰您自己的 OSGI 部署;因此,您必须检查问题并组织部署脚本。
问题很丰富,分析也很复杂。进一步的考虑必须考虑要构建的应用程序的性质。此外,如果您打算使用开源 Spring 和/或 Camel 等开发框架,以及 Oracle Fusion SOA 组合、JBoss Switchyard 等供应商特定框架,您将需要考虑许多其他技术限制。
在这些问题上没有“一刀切”的答案,从本质上讲,这证明了当前过多的重叠技术是合理的。
当架构问题第一次解决后,您可以寻求通过合适的配置管理和部署存储库来优化生产力。
【讨论】:
我很好奇你是否听说过Enterprise OSGi?它就像5岁。您在第 1 部分中的陈述看起来很奇怪,并不是说具有误导性。 我并不是想说,例如,事务服务不存在(又名 OSGi 事务控制服务!),但您确实需要明确地关心划定事务范围和注册资源,因此产生相关的编码,特别是与 EE 容器中的隐式或声明式风格。我原来的措辞确实具有误导性,我修正了它们。感谢您的评论。 事务在OSGi Compendium Release 7 – Transaction Control Service Specification 中处理。对所采取的方法有很好的说明 - OSGi R7 Highlights: Transaction Control【参考方案2】:有多种方法可以将依赖包部署到 OSGi 容器。以下是其中一些:
1 Felix OBR 包存储库
您首先需要使用 bindex 等工具为可用的捆绑包创建 XML 索引文件。如果您使用的是 maven-bundle-plugin,那么它会自动在 ~/.m2/repository/repository.xml 中维护一个 OBR 索引。
使用 OBR 命令行界面加载索引:
> obr:addUrl file:/Users/derek/.m2/repository/repository.xml
然后让 OBR 部署您的目标包,并根据 OBR 索引确定依赖项:
> obr:deploy com.paremus.posh.sshd
Target resource(s):
-------------------
Paremus Posh Ssh Daemon (1.0.23.SNAPSHOT)
Required resource(s):
---------------------
Paremus Command API (1.0.23.SNAPSHOT)
Optional resource(s):
---------------------
Paremus Config Admin Commands (1.0.23.SNAPSHOT)
Paremus OSGi & LDAP Types (1.0.23.SNAPSHOT)
2 阿帕奇卡拉夫
Karaf 支持“功能”,基本上是提供功能所需的捆绑包列表:
karaf@root> features:info obr
Description of obr 2.0.0 feature
----------------------------------------------------------------
Feature has no configuration
Feature has no dependencies.
Feature contains followed bundles:
mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4
mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.0.0
mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.0.0
karaf@root> features:install obr
3 日食处女座
Virgo 使用 plans 来定义组成应用程序的工件,并且它能够 从本地和远程存储库自动提供应用程序的依赖项,包括捆绑包、计划、计划存档 (PAR) 和配置。
4 帕雷姆斯敏捷
Nimble 使用 OBR(或它自己的扩展)存储库索引来自动部署激活目标包所需的所有依赖包(并在目标包停止时卸载它们)。它还可以检测其他依赖项,例如 WAB 包需要 Web 扩展程序并根据可配置策略自动安装。
Nimble 还可以配置为启动 Glassfish,以便其功能可用于 Glassfish 容器中的捆绑包。
下面的示例还显示了在激活 sshd 时自动安装日志记录支持:
$ posh
________________________________________
Welcome to Paremus Nimble!
Type 'help' for help.
[denzil.0]% nim:add --dry-run com.paremus.posh.sshd@active
-- sorted parts to install --
4325 osgi.resolved.bundle/ch.qos.logback.core:0.9.22
-- start dependency loop --
5729 osgi.resolved.bundle/com.paremus.util.logman:1.0.23.SNAPSHOT
5727 osgi.active.bundle/com.paremus.util.logman:1.0.23.SNAPSHOT
3797 osgi.resolved.bundle/ch.qos.logback.classic:0.9.25.SNAPSHOT
3792 osgi.resolved.bundle/slf4j.api:1.6
-- end dependency loop --
436 osgi.resolved.bundle/org.apache.mina.core:2.0.0.RC1
6533 osgi.resolved.bundle/sshd-core:0.3
398 osgi.resolved.bundle/com.paremus.posh.sshd:1.0.23.SNAPSHOT
396 osgi.active.bundle/com.paremus.posh.sshd:1.0.23.SNAPSHOT
(免责声明:我是 Paremus 的开发人员)
5 Apache Felix Gogo
gogo 是新的 RFC147 标准命令行 shell。它已在 Felix、Karaf、Nimble 中使用,并且很快将在 Glassfish 中使用。
Gogo 允许您以脚本的形式运行您可以交互键入的任何命令。因此,您可以生成要安装的捆绑包列表并将其转换为脚本,甚至可以从工作配置中捕获已安装的捆绑包,以便可以从头开始重新创建。
【讨论】:
OBR 绝对看起来是正确的,尤其是因为可以远程登录到 Glassfish 上的 Felix 控制台。唯一看起来不完美的是它将部署未使用的可选传递依赖项。虽然理论上这些类不会被加载,因为它们没有被使用?我说的是令人讨厌的东西,比如 Spring 具有的“jmx”依赖项,这些依赖项最终将由 Glassfish(或 JBoss 或其他)提供【参考方案3】:如果您创建一个 OSGi 应用程序和一个经典 Java 应用程序做同样的事情并使用相同的库,那么您将需要完全相同的 JAR 集。最大的区别在于能够显式定义您的依赖项(并可能为您的应用程序生成更精细的 JAR)。
据我所知,只有一种纯 OSGi 服务器(Eclipse 的 Virgo,以前是 Spring 的 DM 服务器)。 Glassfish 和 Websphere 支持 OSGi,但我没有玩过它们,所以我不能说太多。我能说的是,它们都需要一个 OSGi 容器,通常是 Eclipse 的 Equinox 或 Apache 的 Felix。
您的问题似乎真的是关于配置应用程序(确定需要部署的内容)。我知道对于 Maven 3.0,他们使用 Eclipse 的 P2 供应框架做了很多工作。
对于您的应用程序,您是部署 EAR 还是 WAR?对于其中任何一个,您的构建系统都需要生成包含所有依赖项的存档,否则它将无法工作。您为什么会遇到问题有点令人困惑,因为人们使用 Maven,因为它为他们的构建进行传递依赖管理。
【讨论】:
除了 Eclipse Virgo(以前是 SpringSource dmServer)之外,还有 Apache Karaf(以前是 Felix Karaf,之前是 ServiceMix Kernel)。见karaf.apache.org 这是一个已部署为 Jboss Spring 存档的应用程序。然而,EAR 工件是巨大的,因为有几十个依赖 JAR。我希望工件不包含依赖项,并且将依赖项显式部署为容器的捆绑包。但是,由于依赖项的数量可能是 30-40,因此我正在寻找一种自动部署依赖包的方法。以上是关于如何部署 OSGi 应用程序和依赖项?的主要内容,如果未能解决你的问题,请参考以下文章