领先一步
VMware 提供培训和认证,助您快速提升。
了解更多dm Server 用户经常询问我们在未来几个版本中的计划。在这篇博文中,我将概述我们路线图上的主要功能。我们遵循 Scrum 实践,因此您可以期待我们的冲刺产生相对频繁的里程碑版本,并且我们在处理新需求和优先级变化方面非常灵活。
共享仓库允许您拥有一个集中位置来管理可安装到 dm Server 实例中的制品。然后,这些共享仓库可以添加到 dm Server 配置中的仓库链的任何位置。
共享仓库就是一个 dm Server 节点,它管理一个文件系统仓库并将其提供给其他节点使用。这些托管仓库的节点称为 dm 仓库节点。共享仓库的数量及其顺序不是固定的 - 您可以自由选择适合您环境的任何仓库结构。
客户端 dm Server 节点使用 REST API 与仓库节点通信。此 REST API 将会被文档化并提供,以便第三方工具能够与共享仓库基础设施集成。我们设想了一些场景,例如创建工具来管理仓库,以及在第三方仓库产品之上实现 REST API 的其他场景。
我们将升级企业捆绑包仓库 (Enterprise Bundle Repository) 的软件,使其作为一个完整的 dm 仓库运行,并提供 REST API 访问。
dm Server 的配置系统已升级,以处理广义的制品抽象,而不是专门处理捆绑包。主要原因是 dm Server 2.0 将支持许多不同的部署单元,而不仅仅是捆绑包和 WAR 文件。
仓库基础设施已得到扩展,使得单一仓库能够管理不同类型的制品。然后,您的 dm Server 节点可以查询仓库以获取所需的所有制品。
dm Server 对 PAR 文件的支持允许您将捆绑包组合成一个逻辑单元。在 PAR 中,捆绑包和服务被放置在一个 范围 (scope) 内,该范围将其与系统的其余部分隔离。这种范围划分确保捆绑包彼此连接,并且优先看到彼此的服务,而不是来自范围之外的服务。范围划分还防止应用程序代码泄漏到全局范围或其他应用程序的范围中。
计划文件(或简称计划)泛化了 PAR,以支持
计划也消除了 PAR 所需的额外打包步骤 - 计划只需引用仓库中的其他制品。
<plan name="greenpages" version="1.0.0" scoped="true" atomic="true">
<artifact type="bundle" name="greenpages.db" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.app" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.jpa" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.web" version="${plan.version}"/>
</plan>
在此示例中,您可以看到一个名为 greenpages、版本为 1.0.0 的计划,它引用了 4 个捆绑包。
计划的 scoped 属性控制计划中的制品是否应该安装到计划特定的范围。禁用范围划分时,制品部署到全局范围,并可供所有其他制品访问。
atomic 属性控制计划中制品的生命周期是否绑定在一起。将计划设为 atomic 意味着计划中单个制品的安装、启动、停止和卸载事件将提升到计划中的所有制品。此外,在 atomic 计划中,dm Server 会防止制品处于不一致的状态。例如,如果一个制品启动失败,dm Server 将停止计划中的所有制品。
计划内部制品声明的顺序很重要。为了支持顺序约束,dm Server 将按照制品在计划中定义的顺序向制品广播生命周期事件。这使得您可以创建在启动时具有顺序依赖关系的捆绑包,而无需担心如何控制部署时的顺序。
计划泛化了当今 dm Server 中可用的许多构造。PAR 等同于一个范围化 (scoped)、原子化 (atomic) 的计划,而库 (library) 等同于一个未范围化 (unscoped)、非原子化 (non-atomic) 的计划。dm Server 内部的子系统构造只是一个未范围化、原子化的计划。
dm Server 2.0 将支持的最令人兴奋的新部署制品之一是配置文件。配置文件就是一个属性文件,它使用 OSGi Config Admin 服务在运行时可用。
配置文件具有完整的生命周期支持,可以在运行时进行更新和刷新。您的应用程序可以订阅其配置文件的刷新通知并相应地进行调整。
与计划结合使用时,配置文件为管理应用程序的外部配置数据提供了极好的机制。考虑以下 JDBC 配置文件:
jdbc.url=jdbc:h2:tcp://localhost/~/greenpages
jdbc.user=greenpages
jdbc.password=pass
jdbc.driverClassName=org.h2.Driver
这个配置文件可以以名称 greenpages.jdbc.dev、版本 1.0 发布到仓库中。然后,在我们的计划中,我们可以引用这个配置文件:
<plan name="greenpages.dev" version="1.0.0" scoped="true" atomic="true">
<artifact type="properties" name="greenpages.jdbc.dev" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.db" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.app" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.jpa" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.web" version="${plan.version}"/>
</plan>
这里,一个名为 greenpages.dev 的计划引用了 greenpages.jdbc.dev 配置文件。现在我们可以构建一个名为 greenpages.prod 的计划,它引用一个不同的配置文件。
为了减少在这种场景中所需的重复,计划本身就是仓库中的制品,因此可以从其他计划中引用。
<plan name="greenpages.bundles" version="1.0.0" abstract="true">
<artifact type="bundle" name="greenpages.db" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.app" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.jpa" version="${plan.version}"/>
<artifact type="bundle" name="greenpages.web" version="${plan.version}"/>
</plan>
<plan name="greenpages.dev" version="1.0.0" scoped="true" atomic="true">
<artifact type="properties" name="greenpages.jdbc.dev" version="${plan.version}"/>
<artifact type="plan" name="greenpages.bundles" version="${plan.version}"/>
</plan>
<plan name="greenpages.prod" version="1.0.0" scoped="true" atomic="true">
<artifact type="properties" name="greenpages.jdbc.prod" version="${plan.version}"/>
<artifact type="plan" name="greenpages.bundles" version="${plan.version}"/>
</plan>
这里,一个名为 greenpages.bundles 的计划被 greenpages.prod 和 greenpages.dev 计划引用。greenpages.bundles 计划被声明为抽象的,阻止其独立部署到 dm Server 中。
我们最近发布了 Bundlor 工具,该工具简化了在 Maven、Ant 和 Eclipse 中创建 OSGi manifest 的过程。我们将随着 dm Server 2.0 发布 Bundlor 的一系列增强功能,包括:
自动版本检测使 Bundlor 能够利用 Maven 或 Ivy 文件中的信息确定包或捆绑包依赖项的版本。目前,这些信息包含在 TEMPLATE.MF 文件或外部属性文件中。
使用版本范围表达式,您可以将输入版本扩展为一个版本范围。这允许将 Maven 或 Ivy 文件中定义的版本在映射到包依赖项时扩展为范围。
批量捆绑包处理将允许大量 JAR 自动转换为捆绑包。JAR 之间的关系用于推断版本信息,因此您在模板中需要编写的代码更少。
我们计划的未来最令人兴奋的功能之一是支持模块化 Web 应用。目前,在 dm Server 1.0 中,可以将应用程序的大多数层拆分为捆绑包,但 Web 层往往会带来问题。静态资源解析、会话共享以及需要从多个贡献者组合 UI,使得此功能对于纯 OSGi 而言成为一个难题。
使用 dm Server 中的模块化 Web 应用支持,您可以将 Web 内容拆分到多个捆绑包中,这些捆绑包称为 web fragments。应用程序中的所有 web fragments 共享相同的 ServletContext 会话状态。每个 web fragment 被分配处理应用程序 URL 空间的子部分,这与 WAR 应用的 Web 上下文映射类似。例如,考虑下面的图:
此图表示一个名为 Spring Travel 的单个 Web 应用,它映射到 /springtravel 上下文路径。Spring Travel 应用由三个 web fragments 组成,每个 fragment 映射到 /springtravel 的子路径。例如,flights web fragment 处理对 /springtravel/flights/* 的请求。
Web fragments 可以动态添加到应用程序中,并且应用程序可以随着这些 fragments 的安装和卸载进行调整。
模块化 Web 应用最有趣的特性是支持 UI 组合。主 web 捆绑包可以定义 Web 应用的基本模板、布局、样式和图像。然后,web fragment 可以为现有页面贡献部分,或者贡献符合主捆绑包提供的某个模板的全新页面。
我们仍在确定这个 UI 模型具体是什么样子,但我希望最初我们能够支持 JSF 作为定义模板和贡献的一种方式。
AMS 团队将扩展其对 dm Server 的支持,以允许跨一组 dm Server 节点执行以下操作:
AMS 负责人 Jennifer Hickey 将在即将发布的博文中详细介绍这方面的内容。
克隆是我们引入的一个功能,旨在解决高级用户面临的一些棘手问题。
克隆解决的第一个问题是共享具有静态状态的捆绑包的问题。静态状态与其定义的类耦合。在 OSGi 中,使用具有静态状态的类的捆绑包不会获得该类自己的版本。作为一个例子,考虑在应用程序中使用 Log4J。
Log4J 将其配置状态存储在静态变量中。当您将应用程序部署为 WAR 文件时,这不太可能成为问题。Log4J 将部署在 WEB-INF/lib 中,并且您的应用程序将拥有自己的 Log4J 类私有副本。然而,在 OSGi 中,您可能会有许多捆绑包共享同一个 Log4J 捆绑包,因此也共享相同的 Log4J 类。
克隆旨在解决的第二个问题称为 pinning。Pinning 阻止您安装依赖于同一第三方捆绑包但版本不同的两个捆绑包。当您安装的两个捆绑包的依赖关系图部分重叠,并且非重叠部分违反 uses 约束时,就会出现 Pinning。考虑下图中所示的情况:
这里,捆绑包 A 依赖于 Spring 2.5.6 和 EclipseLink 1.0.0。这种依赖配置没问题,假设满足所有其他依赖项,捆绑包将正确安装。
现在考虑当我们想引入第二个捆绑包 捆绑包 B,并且我们希望这个捆绑包依赖于 Spring 2.5.6,同时我们想将 EclipseLink 的版本升级到 1.0.1 时会发生什么。
您可以看到 捆绑包 B 和 EclipseLink 1.0.1 之间的依赖是可以满足的,但 捆绑包 B 无法连接到 Spring 2.5.6。原因是 Spring 对所有 org.eclipse.persistence 包都有一个 uses 约束。这个约束阻止 捆绑包 B 连接到 Spring 2.5.6 以及一个 EclipseLink 捆绑包,除非它连接到与 Spring 2.5.6 相同的 EclipseLink 捆绑包。关于 uses 的更多信息可以在 Glyn 的介绍性博文和我的关于诊断 uses 失败的博文中找到。
为了解决这些问题,克隆提供了创建捆绑包托管克隆的能力,并将其绑定到应用程序的作用域中。在使用 Import-Bundle 引用捆绑包时,可以手动调用克隆。您可以使用此方法为应用程序捆绑包创建 Log4J 的克隆。
Manifest-Version: 1
Bundle-ManifestVersion: 2.0
Bundle-SymbolicName: app.bundle
Bundle-Version: 1.0.0
Import-Bundle: com.springsource.org.apache.log4j;bundle-version="1.3.4";sharing:=clone
当这被安装到 dm Server 中时,您将获得类似以下内容:
这里,在 app.bundle 的作用域(由虚线表示)中创建了一个 Log4J 捆绑包的克隆。
如果 dm Server 遇到 uses 约束冲突,克隆将在供应期间自动触发。回顾前面 捆绑包 B 和 EclipseLink 1.0.1 的例子,克隆将产生以下结果:
在供应期间,dm Server 检测到 捆绑包 B 的依赖项无法满足,并创建一个 Spring 2.5.6 的克隆来解决此问题。
dm Server 运行时管理模型将完全理解克隆。您可以查询附加到给定捆绑包的克隆,并且对捆绑包的更新和刷新也会影响该捆绑包的克隆。
我们收到了很多关于 dm Server 1.0 中日志和跟踪支持的反馈,在 2.0 版本中,我们将解决用户提出的最紧迫的问题。
对于 dm Server 2.0,我们将彻底改造所有跟踪功能,使其运行在 SLF4J 之上,底层使用 LogBack 实现。此外,我们的日志框架将被重新设计,使其作为 SLF4J 之上的一个薄层。
我们将提供一系列 LogBack(可能还有 Log4J)的 appender,它们将用户和应用程序特定的跟踪路由到 dm Server 的跟踪文件中。这里最值得关注的可能是选择性地选择哪些捆绑包写入应用程序特定跟踪的能力。同样重要的是要注意,在使用应用程序特定跟踪时,应用程序目的地是根据 dm Server 内部当前的“工作单元”动态选择的。这意味着同一个共享库可以根据其用法将跟踪写入不同的应用程序跟踪文件。
我对一个特性感到兴奋,那就是支持从仓库部署 LogBack 配置。一旦配置安装到 dm Server 中,捆绑包可以选择绑定到该配置作为其日志配置源。这提供了一种简单机制,支持多个不同的日志配置并行存在,并在多个捆绑包之间共享日志配置。
今年应该会看到专门针对企业用途的 OSGi 规范首次发布。我们积极参与此过程,并打算让 dm Server 2.0 成为运行企业 OSGi 应用程序的最佳场所。我们将支持:
RFC124 的参考实现正在由 SpringSource 基于 Spring Dynamic Modules 中完成的工作创建。我们还在使用 dm Server 1.0 中已有的 Web 应用程序支持来构建 RFC66 的参考实现。
管理 shell 提供安全、命令行的 dm Server 管理功能访问。使用管理 shell,您可以:
管理 shell 完全支持插件,可以轻松添加自定义命令。
由于广泛的需求,我们将从 dm Server 特定机制配置 Tomcat 切换回使用 Tomcat 自身的配置文件格式。
在接下来的几天里,我们将发布 dm Server 2.0 M1,其中将包含我们计划和共享仓库功能的预览。从那时起,我们希望能够定期发布里程碑版本,直至我们计划于 7 月某个时候发布的最终版本。