SpringSource dm 服务器路线图

工程 | Rob Harrop | 2009年4月1日 | ...

我们收到 dm 服务器用户许多关于未来几个版本预期功能的问题。在这篇博客文章中,我将概述我们路线图上的主要功能。我们遵循 Scrum 实践,因此您可以预期会看到我们冲刺输出的相当频繁的里程碑,并且我们能够灵活地处理新的需求和优先级的变化。

共享仓库

共享仓库允许您拥有一个集中位置来管理可在您的 dm 服务器实例中安装的构件。然后,这些共享仓库可以在其仓库链中的任何点添加到 dm 服务器配置中。

一个**共享仓库**只是一个 dm 服务器节点,它管理一个文件系统仓库并使其可供其他节点使用。这些仓库托管节点称为**dm 仓库节点**。共享仓库的数量及其顺序不是固定的——您可以自由选择适合您的环境的任何仓库结构。

客户端 dm 服务器节点使用 REST API 与仓库节点通信。此 REST API 将被记录并提供,以便第三方工具可以与共享仓库基础设施集成。我们设想可以通过创建工具来管理仓库,以及在第三方仓库产品之上实现 REST API 的其他场景。

我们将升级我们的企业捆绑包仓库的软件,使其作为完整的 dm 仓库运行,并提供完整的 REST API 访问。

仓库和配置增强

dm 服务器配置系统已升级为处理通用的构件抽象,而不是专门处理捆绑包。这样做的主要原因是 dm 服务器 2.0 将支持许多不同的部署单元,而不仅仅是捆绑包和 WAR 文件。

仓库基础设施已扩展,允许单个仓库管理不同类型的构件。然后,您的 dm 服务器节点可以查询仓库以获取其所需的所有构件。

计划文件

dm 服务器中对 PAR 文件的支持允许您将捆绑包组合在一起作为单个逻辑单元。在 PAR 中,捆绑包和服务被放置在一个**作用域**中,将其与系统的其余部分隔离。此作用域确保捆绑包相互连接并优先查看彼此的服务,而不是来自作用域外部的服务。作用域还可以防止应用程序代码泄漏到全局作用域或其他应用程序的作用域。

计划文件(或简称为计划)将 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**属性控制计划中构件的生命周期是否应绑定在一起。使计划原子化意味着单个构件的安装、启动、停止和卸载事件将被提升到计划中的所有构件。此外,在原子计划中,dm 服务器可防止构件处于不一致的状态。例如,如果一个构件无法启动,则 dm 服务器将停止计划中的所有构件。

计划内构件声明的顺序很重要。为了支持排序约束,dm 服务器将按计划中定义的顺序向构件广播生命周期事件。这允许您创建在启动期间具有排序依赖关系的捆绑包,而无需担心如何控制部署时间的排序。

计划概括了当今 dm 服务器中提供的许多构造。PAR 等效于作用域的原子计划,而库等效于非作用域的非原子计划。dm 服务器内部的子系统构造只是一个非作用域的原子计划。

配置配置

dm 服务器 2.0 将支持的最令人兴奋的新部署构件之一是配置文件。配置文件只是一个在运行时使用 OSGi 配置管理服务提供的属性文件。

配置文件具有完整生命周期支持,可以在运行时更新和刷新。您的应用程序可以订阅其配置文件刷新的通知并相应地进行调整。

与计划结合使用时,配置文件提供了一种管理应用程序外部配置数据的极好机制。考虑此 JDBC 配置文件


jdbc.url=jdbc:h2:tcp://127.0.0.1/~/greenpages
jdbc.user=greenpages
jdbc.password=pass
jdbc.driverClassName=org.h2.Driver

此配置文件可以以版本**1.0**的名为**greenpages.jdbc.dev**发布到仓库中。然后,在我们的计划中,我们可以引用此配置文件

<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 服务器中。

构建增强

我们最近宣布了我们的 Bundlor 工具,它简化了在 Maven、Ant 和 Eclipse 中创建 OSGi 清单文件。我们将与 dm 服务器 2.0 一起发布许多 Bundlor 的增强功能,包括

  • 从 Maven 和 Ivy 文件自动检测版本
  • 支持 bnd 样式的版本范围表达式
  • 批量捆绑包处理

自动版本检测使 Bundlor 能够使用 Maven 或 Ivy 文件中的信息来确定包或捆绑包依赖项的版本。当前,此信息包含在**TEMPLATE.MF**文件中或外部属性文件中。

使用版本范围表达式,您可以将输入版本扩展到版本范围。这允许在映射到包依赖项时将 Maven 或 Ivy 文件中定义的版本扩展为范围。

批量捆绑包处理将允许将大量 JAR 自动转换为捆绑包。JAR 之间的关系用于推断版本信息,因此您需要编写的模板代码更少。

模块化 Web 应用

我们为未来规划的最令人兴奋的功能之一是支持模块化 Web 应用程序。当前,在 dm 服务器 1.0 中,可以将应用程序的大多数层拆分为捆绑包,但 Web 层往往会带来问题。静态资源解析、会话共享以及需要组合来自多个贡献者的 UI 使此功能成为普通 OSGi 的问题。

使用 dm 服务器中的模块化 Web 应用程序支持,您将能够在多个捆绑包(称为**Web 片段**)中拆分 Web 内容。应用程序中的所有 Web 片段共享相同的**ServletContext**会话状态。每个 Web 片段都被分配来处理应用程序的 URL 空间的子部分,这与使用 WAR 应用程序进行 Web 上下文映射的方式非常相似。例如,考虑下面的图表

mwa-example

此图表示一个单一的 Web 应用程序 Spring Travel,它映射到** /springtravel**上下文路径。Spring Travel 应用程序由三个 Web 片段组成,每个片段都映射到** /springtravel**的子路径。例如,**flights** Web 片段服务对** /springtravel/flights/***的请求。

可以动态地将 Web 片段添加到应用程序,并且应用程序可以在安装和卸载这些片段时进行调整。

模块化 Web 应用程序最有趣的功能是支持 UI 组合。Web 主捆绑包可以定义 Web 应用程序的基本模板、布局、样式和图像。然后,Web 片段可以向现有页面贡献部分或整个新页面,这些页面适合主程序提供的模板之一。

我们仍在定义此 UI 模型的精确外观,但我希望我们最初能够支持 JSF 作为定义模板和贡献的一种方式。

分布式管理

AMS 团队将扩展其 dm 服务器支持,以允许对一组 dm 服务器节点执行以下操作

  • 构件安装/卸载
  • 构件启动/停止
  • 构件刷新
  • 仓库发布/删除

AMS 负责人 Jennifer Hickey 将在即将发表的博客文章中详细介绍这一点。

克隆

克隆是我们引入的一项功能,用于解决我们的高级用户面临的许多棘手问题。

克隆解决的第一个问题是共享具有静态状态的捆绑包的问题。静态状态与定义静态字段的类耦合。在 OSGi 中,使用具有静态状态的类的捆绑包**不会**获得该类自己的版本。作为此问题的示例,请考虑在应用程序中使用 Log4J。

Log4J 将其配置状态存储在静态变量中。当您将应用程序部署为 WAR 文件时,这不太可能成为问题。Log4J 将部署在 **WEB-INF/lib** 中,您的应用程序将拥有自己私有的 Log4J 类副本。但是,在 OSGi 中,您可能会有许多捆绑包共享相同的 Log4J 捆绑包,因此也共享相同的 Log4J 类。

克隆旨在解决的第二个问题称为 **锁定(pinning)**。锁定阻止您安装两个依赖于相同第三方捆绑包但版本不同的捆绑包。当您要安装的两个捆绑包的依赖关系图部分重叠时,且非重叠部分破坏了 uses 约束,就会出现锁定问题。请考虑下图中的情况。

cloning-start

这里 **捆绑包 A** 依赖于 **Spring 2.5.6** 和 **EclipseLink 1.0.0**。此依赖关系配置文件很好,如果满足所有其他依赖关系,则捆绑包将正确安装。

现在考虑一下当我们想要引入第二个捆绑包 **捆绑包 B**,并且希望此捆绑包依赖于 **Spring 2.5.6**,并且希望将 EclipseLink 的版本升级到 1.0.1 时会发生什么。

cloning-full

您可以看到 **捆绑包 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 后,您将获得如下内容:

cloning-log4j

这里,在 **app.bundle** 的范围内(由虚线表示)创建了 Log4J 捆绑包的克隆。

如果 dm Server 遇到 uses 约束冲突,则在供应过程中将自动触发克隆。重新审视前面 **捆绑包 B** 和 **EclipseLink 1.0.1** 的示例,克隆将给出以下结果:

cloning-auto-fixed

在供应过程中,dm Server 检测到无法满足 **捆绑包 B** 的依赖关系,并创建 **Spring 2.5.6** 的克隆来解决此问题。

dm Server 运行时管理模型将完全理解克隆。您可以查询附加到给定捆绑包的克隆,并且对捆绑包的更新和刷新也会影响该捆绑包的克隆。

改进的日志记录和跟踪支持

我们收到了很多关于 dm Server 1.0 中的日志记录和跟踪支持的反馈,在 2.0 中,我们将解决用户提出的最紧迫的问题。

对于 dm Server 2.0,我们将彻底修改所有跟踪,使其在 SLF4J 之上运行,并在其下方使用 LogBack 实现。此外,我们的日志记录框架将被重新设计为位于 SLF4J 之上的薄层。

我们将提供一系列 LogBack(可能还有 Log4J)追加器,它们将把用户和应用程序特定的跟踪路由到 dm Server 跟踪文件中。这里最令人感兴趣的可能是能够选择性地选择要为其写入应用程序特定跟踪的捆绑包。同样重要的是要注意,当使用应用程序特定跟踪时,应用程序目标是根据 dm Server 内部的当前工作单元动态选择的。这意味着同一个共享库可以将其跟踪写入不同的应用程序跟踪文件,具体取决于其用法。

我感到兴奋的一个功能是从存储库部署 LogBack 配置的支持。将配置安装到 dm Server 后,捆绑包可以选择将其绑定到该配置作为其日志记录配置源。这提供了一种易于支持并排使用多个不同日志配置以及跨多个捆绑包共享日志记录配置的机制。

企业 OSGi

今年应该会看到第一个专门针对企业使用的 OSGi 规范版本发布。我们积极参与此过程,我们打算让 dm Server 2.0 成为运行企业 OSGi 应用程序的最佳场所。我们将支持:

  • RFC66 - OSGi 的 Web 容器
  • RFC119 - 分布式 OSGi
  • RFC124 - 蓝图服务(源自 Spring Dynamic Modules 中的工作)
  • RFC139 - OSGi 的 JMX 接口
  • RFC142 - JNDI 和 OSGi 集成

RFC124 的参考实现正在由 SpringSource 基于 Spring Dynamic Modules 中完成的工作创建。我们还使用 dm Server 1.0 中已存在的 Web 应用程序支持来构建 RFC66 的参考实现。

管理 shell

管理 shell 提供对 dm Server 管理功能的安全命令行访问。使用管理 shell,您可以:

  • 管理已配置的存储库
  • 安装/卸载工件
  • 启动/停止工件
  • 更新/刷新工件
  • 查询工件依赖关系图
  • 查询正在运行的服务
  • 诊断依赖关系解析问题

管理 shell 完全可插拔,允许轻松添加自定义命令。

Tomcat 配置

由于大众需求,我们将从 dm Server 特定的 Tomcat 配置机制切换回使用 Tomcat 自身的配置文件格式。

接下来是什么?

在接下来的几天里,我们将发布 dm Server 2.0 M1,其中将包含我们计划和共享存储库功能的预览。从那时起,我们希望能够定期发布里程碑版本,直到我们最终在 7 月份某个时候发布最终版本。

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部