部署到 Apache Karaf

Red Hat Fuse 7.11

将应用程序软件包部署到 Apache Karaf 容器中

Red Hat Fuse Documentation Team

摘要

本指南描述了将应用程序部署到 Apache Karaf 容器中的选项。

使开源包含更多

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。详情请查看我们的 CTO Chris Wright 信息

部分 I. 开发人员指南

这部分包含开发人员的信息。

第 1 章 OSGi 简介

摘要

OSGi 规范通过定义运行时框架来支持模块化应用程序开发,以简化构建、部署和管理复杂应用程序。

1.1. 概述

Apache Karaf 是基于 OSGi 的运行时容器,用于部署和管理捆绑包。Apache Karaf 还提供原生操作系统集成,并可集成到操作系统中,作为服务集成,以便生命周期与操作系统绑定。

Apache Karaf 具有以下结构:

  • Apache Karaf - 围绕 OSGi 容器实施的一个打包程序层,为将 OSGi 容器部署为运行时服务器提供支持。Fuse 提供的运行时功能包括热部署、管理和管理功能。
  • OSGi Framework - 实施 OSGi 功能,包括管理依赖关系和捆绑生命周期

1.2. Apache Karaf 架构

Apache Karaf 使用以下功能扩展了 OSGi 层:

  • 控制台 - 控制台管理服务,安装和管理应用程序及库,并与 Fuse 运行时进行交互。它提供了控制台命令来管理 Fuse 实例。请参阅 Apache Karaf 控制台参考
  • logging - logging 子系统提供显示、查看和更改日志级别的控制台命令。
  • 部署 - 支持使用捆绑包( install 和 bundle: start 命令和热部署应用程序)手动部署 OSGi 捆绑包。请参阅 第 6.1 节 “热部署”
  • 置备 - 提供多个安装应用程序和库的机制。请参阅 第 9 章 部署功能
  • 配置 - 存储在 InstallDir/etc 文件夹中的属性文件将持续监控,并且更改以可配置的间隔自动传播到相关服务。
  • 蓝图 - 是一个依赖项注入框架,简化了与 OSGi 容器的交互。例如,提供标准 XML 元素以导入和导出 OSGi 服务。当将 Blueprint 配置文件复制到热部署文件夹时,红帽 Fuse 会即时生成 OSGi 捆绑包,并实例化 Blueprint 上下文。

1.3. OSGi Framework

1.3.1. 概述

OSGi 联盟 是一个独立组织,负责定义 OSGi 服务平台版本 4 的特性和功能。OSGi 服务平台是一组开放规范,可简化构建、部署和管理复杂软件应用程序。

OSGi 技术通常被称为 Java 的动态模块系统。OSGi 是 Java 的框架,它使用捆绑包模块化地部署 Java 组件并处理依赖项、版本控制、类路径控制和类加载。OSGi 的生命周期管理允许您在不关闭 JVM 的情况下加载、启动和停止捆绑包。

OSGi 为 Java、卓越的类加载架构和服务的注册表提供最佳的运行时平台。捆绑包可以导出服务、运行进程以及其依赖项。每个捆绑包都可以满足其由 OSGi 容器管理的要求。

Fuse 使用 Apache Felix 作为其默认的 OSGi 实施。框架层形成安装捆绑包的容器。框架以动态、可扩展的方式管理捆绑包的安装和更新,并管理捆绑和服务之间的依赖关系。

1.3.2. OSGi 架构

OSGi 框架包含以下内容:

  • 捆绑 - 组成应用程序的逻辑模块。请参阅 第 1.5 节 “OSGi 捆绑包”
  • 服务级别 - 提供模块及其所含组件之间的通信。这个层与生命周期层紧密集成。请参阅 第 1.4 节 “OSGi 服务”
  • 生命周期阶段 - 提供对底层 OSGi 框架的访问。这个层处理单个捆绑包的生命周期,以便您可以动态管理应用程序,包括启动和停止捆绑包。
  • 模块层 - 提供 API 以管理捆绑打包、依赖项解析和类加载。
  • 执行环境 - JVM 的配置。此环境使用配置文件来定义捆绑包中可正常工作的环境。
  • 安全层 - 基于 Java 2 安全性的可选层,额外限制和增强。

框架中的每个层取决于它下面的层。例如,生命周期层需要模块层。模块层可以在无生命周期和服务层的情况下使用。

1.4. OSGi 服务

1.4.1. 概述

OSGi 服务是一个 Java 类或服务接口,其服务属性定义为名称/值对。服务属性区分有同一服务接口的服务提供程序。

OSGi 服务由其服务接口定义语义,它作为服务对象实施。服务的功能由它实施的接口定义。因此,不同的应用程序可以实施相同的服务。

服务接口允许捆绑包通过绑定接口而不是实现交互。服务接口应尽可能少地指定一些实施详情。

1.4.2. OSGi 服务 registry

在 OSGi 框架中,服务层使用发布、查找和绑定服务模型提供 第 1.5 节 “OSGi 捆绑包” 与所含组件之间的通信。服务层包含一个服务 registry,其中:

  • 服务提供商在框架中注册服务,供其他捆绑包使用
  • Service requesters 查找服务并绑定到服务供应商

服务归所有,在捆绑包内运行。捆绑包在一个或多个 Java 接口下将服务的实施注册到框架服务 registry。因此,该服务的功能可供框架控制下的其他捆绑包使用,其他捆绑包可以查找并使用该服务。使用 Java 接口和服务属性执行查找。

每个捆绑包都可以使用其接口及其属性的完全限定名称在服务注册表中注册多个服务。捆绑包使用带 LDAP 语法的名称和属性来查询服务 registry。

捆绑包负责运行时服务依赖关系管理活动,包括发布、发现和绑定。捆绑包还可适应与捆绑包绑定的服务动态可用性(arrival 或 departure)带来的变化。

事件通知

服务接口由捆绑包创建的对象实施。捆绑包可以:

  • 注册服务
  • 搜索服务
  • 当其注册状态更改时接收通知

OSGi 框架提供了事件通知机制,因此服务请求者可以在服务 registry 中的更改时收到通知事件。这些更改包括发布或检索特定服务以及何时注册、修改或取消注册服务。

服务调用模型

当捆绑包想要使用服务时,它会查找该服务并以普通 Java 调用形式调用 Java 对象。因此,服务上的调用是同步的,并在同一线程中发生。您可以使用回调进行更异步处理。参数作为 Java 对象引用传递。对于 XML,不需要 marshall 或中间规范格式。OSGi 为服务不可用问题提供了解决方案。

OSGi 框架服务

除您自己的服务外,OSOS 框架还提供以下可选服务来管理框架的操作:

  • 软件包管理服务- 允许管理代理通过检查共享软件包的状态来定义用于管理 Java 软件包共享的策略。它还允许管理代理刷新软件包,并根据需要停止和重启捆绑包。此服务使管理代理可以在卸载或更新捆绑包时对任何共享软件包做出决定。

    该服务还提供刷新从上次刷新后删除或更新的软件包,并明确解析特定捆绑包的方法。此服务也可以在运行时跟踪捆绑包之间的依赖关系,允许您查看哪些捆绑包会受到升级的影响。

  • 启动级别服务- 允许管理代理控制捆绑包的启动和停止顺序。该服务为每个捆绑包分配一个启动级别。管理代理可以修改捆绑包的启动级别,并设置框架的活跃启动级别,这将启动并停止适当的捆绑包。只有起始级别低于(或等于)的捆绑包,这个活跃的启动级别可以活跃。
  • URL 处理程序服务- 动态地使用 URL 方案和内容处理程序扩展 Java 运行时,支持任何组件提供额外的 URL 处理程序。
  • 权限管理员服务- 启用 OSGi 框架管理代理以管理特定捆绑包的权限,并提供所有捆绑包的默认值。捆绑包可以具有一组用于验证是否有权执行特权代码的权限。您可以通过实时更改策略以及为新安装组件添加新策略来动态操作权限。策略文件用于控制可运行哪些捆绑包。
  • 条件权限管理员服务- 在检查权限时,使用权限扩展 Permission Admin 服务,可在特定条件为 true 或 false 时应用。这些条件决定了权限应用到的捆绑包选择。设置后会立即激活权限。

在 OSGi 服务 平台版本 4 规范中对 OSGi 框架服务进行详细介绍,请参阅 OSGi 联盟网页上 发布的 4 下载页面

OSGi Compendium 服务

除了 OSGi 框架服务外,OSOS 联盟还定义了一组可选的、标准化的编译服务。OSGi 编译服务为日志记录和首选项等任务提供 API。在 OSGi 联盟 Web 站点上 版本 4 下载页面 的 OSGi 服务平台 Service Compendium 中介绍了这些服务。

Configuration Admin compendium 服务类似于中央中心,可保留配置信息并将其分发给关注方。Configuration Admin 服务指定部署捆绑包的配置信息,并确保捆绑包在激活时接收这些数据。捆绑包的配置数据是一个名称值对列表。请参阅 第 1.2 节 “Apache Karaf 架构”

1.5. OSGi 捆绑包

概述

借助 OSGi,您将应用程序模块化到捆绑包中。每个捆绑包都是一个紧密耦合的、可动态加载的类、JAR 和配置文件的集合,该文件明确声明任何外部依赖项。在 OSGi 中,捆绑包是主要的部署格式。捆绑包(bundle)是打包在 JAR 中的应用程序,可以安装、启动、停止、更新和删除应用程序。

OSGi 为开发捆绑包提供了一个动态、简洁、一致的编程模型。开发和部署可通过从其实施中分离服务规格(Java 接口)来简化。

OSGi 捆绑包抽象允许模块共享 Java 类。这是静态的重复使用形式。当依赖捆绑包启动时,必须可用共享类。

捆绑包是 JAR 文件,在其 OSGi 清单文件中包含元数据。捆绑包包含类文件,以及可选的其他资源和原生库。您可以明确声明捆绑包中的哪些软件包在外部可见(导出的软件包)以及捆绑包需要哪些外部软件包(导入的软件包)。

模块层处理捆绑包与从其他捆绑包中打包和共享软件包之间的打包和共享。OSGi 框架会在捆绑包间动态地解决依赖项。框架执行捆绑包解析,以匹配导入和导出的软件包。它还可管理多个版本的部署捆绑包。

OSGi 中的类加载

OSGi 使用图形模型进行类加载,而非树结构模型(供 JVM 使用)。捆绑可以以标准化的方式共享和重新使用类,不会加载运行时类冲突。

每个捆绑包都有自己的内部类路径,以便在需要时可以作为独立单元服务。

OSGi 中类载入的好处包括:

  • 直接在捆绑包间共享类。不需要将 JAR 提升到父类加载程序。
  • 您可以同时部署同一类的不同版本,且无冲突。

第 2 章 启动和停止 Apache Karaf

摘要

Apache Karaf 提供简单的命令行工具,用于启动和停止服务器。

2.1. 启动 Apache Karaf

部署 Apache Karaf 运行时的默认方法是将它部署为具有活跃控制台的单机服务器。您还可以在不控制台的情况下将运行时部署为后台进程。

2.1.1. 设置您的环境

您可以直接从安装的 bin 子目录中启动 Karaf 运行时,而无需修改您的环境。但是,如果您要在不同的文件夹中启动它,则需要将 glibc 安装的 bin 目录添加到 PATH 环境变量中,如下所示:

Windows

set PATH=%PATH%;InstallDir\bin

Linux/UNIX

export PATH=$PATH,InstallDir/bin`

2.1.2. 以控制台模式启动运行时

如果您要从安装目录中启动 Quarkus 运行时,请使用以下命令:

Windows

bin\fuse.bat

Linux/UNIX

./bin/fuse

如果 Karaf 启动正确,您应该在控制台中看到以下内容:

Red Hat Fuse starting up. Press Enter to open the shell now...
100% [========================================================================]

Karaf started in 8s. Bundle stats: 220 active, 220 total

 ____          _   _   _       _     _____
|  _ \ ___  __| | | | | | __ _| |_  |  ___|   _ ___  ___
| |_) / _ \/ _` | | |_| |/ _` | __| | |_ | | | / __|/ _ \
|  _ <  __/ (_| | |  _  | (_| | |_  |  _|| |_| \__ \  __/
|_| \_\___|\__,_| |_| |_|\__,_|\__| |_|   \__,_|___/___|

  Fuse (7.x.x.fuse-xxxxxx-redhat-xxxxx)
  http://www.redhat.com/products/jbossenterprisemiddleware/fuse/

Hit '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.

Open a browser to http://localhost:8181/hawtio to access the management console

Hit '<ctrl-d>' or 'shutdown' to shutdown Red Hat Fuse.

karaf@root()>
注意

自 Fuse 6.2.1 起,启动控制台模式会创建两个进程:父进程 ./bin/karaf,即执行 Karaf 控制台;以及子进程,它在 java JVM 中执行 Karaf 服务器。但是,关闭的行为与以前相同。也就是说,您可以使用 Ctrl-D 或 osgi:shutdown 从控制台关闭服务器,从而终止这两个进程。

2.1.3. 以服务器模式启动运行时

在服务器模式中启动,可在后台运行 Apache Karaf,无需本地控制台。然后,您要使用远程控制台连接到正在运行的实例。详情请查看 第 17.2 节 “在远程连接和断开连接”

要在服务器模式中启动 Karaf,请运行以下命令

Windows

bin\start.bat

Linux/UNIX

./bin/start

2.1.4. 以客户端模式启动运行时

在生产环境中,您可能希望仅使用本地控制台访问运行时实例。换句话说,您无法通过 SSH 控制台端口远程连接到运行时。您可以使用以下命令在客户端模式中启动运行时:

Windows

bin\fuse.bat client

Linux/UNIX

./bin/fuse client
注意

在客户端模式中启动仅阻止 SSH 控制台端口(通常是端口 8101)。其他 Karaf 服务器端口(例如,JMX 管理 RMI 端口)正常打开。

2.1.5. 在 debug 模式下运行 Fuse

在调试模式下运行 Fuse 有助于更有效地识别和解决错误。默认禁用这个选项。启用之后,Fuse 在端口 5005 上启动 JDWP 套接字。

您可以通过三种方法 在调试模式下运行 Fuse。

2.1.5.1. 使用 Karaf 环境变量

这个方法启用 KARAF_DEBUG 环境变量(=1),然后启动容器。

$ export KARAF_DEBUG=1
$ bin/start

2.1.5.2. 运行 Fuse debug

此方法运行 debug,其中 suspend 选项设置为 n (无)。

$ bin/fuse debug

2.1.5.3. 运行 Fuse debugs

此方法运行 debug,其中 suspend 选项设置为 y (是)。

注意

suspend 设为 yes 会导致 JVM 仅在运行 main() 之前暂停,然后它会恢复执行。

$ bin/fuse debugs

2.2. 停止 Apache Karaf

您可以从控制台或停止脚本 来停止 Apache Karaf 实例。

2.2.1. 从本地控制台停止实例

如果您通过运行 fusefuse 客户端 启动 visual 实例,您可以在 karaf > 提示下执行以下操作之一来停止它:

  • 类型 关闭
  • Ctrl+D

2.2.2. 停止以服务器模式运行的实例

您可以通过从 InstallDir/bin 目录调用 stop(.bat) 来停止本地运行的 Karaf 实例(root 容器),如下所示:

Windows

bin\stop.bat

Linux/UNIX

./bin/stop

Karaf stop 脚本调用的关闭机制与 Apache Tomcat 中实施的关闭机制类似。Karaf 服务器打开专用的关闭端口(与 SSH 端口不同),以接收关闭通知。默认情况下,会随机选择关闭端口,但是如果愿意,您可以将该端口配置为使用特定的端口。

您可以选择通过在 InstallDir/etc/config.properties 文件中设置以下属性来自定义关闭端口:

karaf.shutdown.port

指定要用作关闭端口的 TCP 端口。将此属性设置为 -1 可禁用端口。默认为 0( 随机端口)。

注意

如果要使用 bin/stop 脚本关闭远程主机上运行的 Karaf 服务器,则需要设置与远程主机的关闭端口相同的属性。但请注意,此设置也会影响位于与 etc/config.properties 文件相同的主机上。

karaf.shutdown.host

指定关闭端口绑定到的主机名。此设置对于多设备主机非常有用。默认为 localhost

注意

如果要使用 bin/stop 脚本关闭远程主机上运行的 Karaf 服务器,则需要将此属性设置为远程主机的主机名(或 IP 地址)。但请注意,此设置也会影响位于与 etc/config.properties 文件相同的主机上。

karaf.shutdown.port.file
在 Karaf 实例启动后,它会将当前的关闭端口写入此属性指定的文件中。stop 脚本读取此属性指定的文件,以发现当前关闭端口的值。默认为 ${karaf.data}/port
karaf.shutdown.command

指定必须发送到关闭端口的 UUID 值以便触发关闭。只要保留 UUID 值,就会提供一个安全性的元素级别。例如,etc/config.properties 文件可以被读取,以防止普通用户读取这个值。

当 Apache Karaf 首次启动时,会自动生成随机 UUID 值,并将此设置写入 etc/config.properties 文件的末尾。或者,如果已经设置了 karaf.shutdown.command,则 Karaf 服务器会使用预先存在的 UUID 值(如果需要,它允许您自定义 UUID 设置)。

注意

如果要使用 bin/stop 脚本关闭远程主机上运行的 Karaf 服务器,则需要将此属性设置为与远程主机的 karaf.shutdown.command 的值相等。但请注意,此设置也会影响位于与 etc/config.properties 文件相同的主机上。

2.2.3. 停止远程实例

您可以停止在远程主机上运行的容器实例,如 第 17.3 节 “停止远程容器” 所述。

第 3 章 基本安全性

本章论述了在第一次引导前配置安全性的基本步骤。默认情况下,ESB 是安全的,但其任何服务都不能被远程访问。本章论述了如何启用对通过 Karaf 公开的端口的安全访问。

3.1. 配置基本安全性

3.1.1. 概述

Apache Karaf 运行时默认对网络攻击进行保护,因为所有公开的端口都需要用户身份验证,而且最初没有定义用户。换句话说,默认情况下可以远程访问 Apache Karaf 运行时。

如果要远程访问运行时,您必须首先自定义安全配置,如下所述。

3.1.2. 在启动容器前

如果要启用到 Karaf 容器的远程访问,您必须在启动容器前创建 secure JAAS 用户:

3.1.3. 创建安全 JAAS 用户

默认情况下,容器没有定义 JAAS 用户,这可有效禁用远程访问(无法登录)。

要创建安全 JAAS 用户,请编辑 InstallDir/etc/users.properties 文件并添加一个新用户字段,如下所示:

Username=Password,admin

其中 UsernamePassword 是新用户凭证。admin 角色授予该用户访问容器的所有管理和管理功能的特权。

不要用前导零定义数字用户名。此类用户名始终会导致登录尝试失败。这是因为 console 使用的 Karaf shell,当输入显示为数字时,丢弃前导零。例如:

karaf@root> echo 0123
123
karaf@root> echo 00.123
0.123
karaf@root>
警告

强烈建议您使用强大密码定义自定义用户凭证。

3.1.4. 基于角色的访问控制

Karaf 容器支持基于角色的访问权限控制,该控制通过 JMX 协议、XDP 命令控制台和 Fuse 管理控制台进行监管。为用户分配角色时,您可以从标准角色集合中选择,它提供了 表 3.1 “访问控制的标准角色” 中描述的访问级别。

表 3.1. 访问控制的标准角色

角色描述

Viewer

授予容器的只读权限。

Manager

授予在适当级别上对普通用户(希望部署和运行应用程序)的读写访问权限。但阻止对敏感容器配置设置的访问。

admin

授予容器的不受限制的访问权限。

ssh

通过 SSH 端口授予对远程控制台访问权限的权限。

有关 基于角色的访问控制 的详情,请参阅基于角色的访问控制。

3.1.5. Apache Karaf 容器公开的端口

容器公开以下端口:

  • 通过 Apache Karaf shell 命令,控制台端口 >_<-admission-enables 对容器实例的远程控制。此端口默认为启用,并且由 JAAS 身份验证和 SSH 保护。
  • JMX 端口 abrt-enables 通过 JMX 协议管理容器。此端口默认为启用,并由 JAAS 身份验证进行保护。
  • Web 控制台端口 & gt;_<-abrtprovides 对可托管 Web 控制台 servlets 的嵌入式 Undertow 容器的访问。默认情况下,Fuse 控制台安装在 Undertow 容器中。

3.1.6. 启用远程控制台端口

您可以同时满足以下条件时访问远程控制台端口:

  • JAAS 配置至少有一组登录凭据。
  • PackageKit 运行时 还没有 以客户端模式启动(客户端模式可完全禁用远程控制台端口)。

例如,要从运行容器的同一机器中登录到远程控制台端口,请输入以下命令:

./client -u Username -p Password

其中,UsernamePassword 是带有 ssh 角色的 JAAS 用户的凭据。通过远程端口访问 Karaf 控制台时,您的权限取决于在 etc/users.properties 文件中分配给用户的角色。如果要访问一组完整的控制台命令,用户帐户必须具有 admin 角色。

3.1.7. 加强远程控制台端口的安全性

您可以使用以下措施加强远程控制台端口的安全性:

  • 确保 JAAS 用户凭据具有强大的密码。
  • 自定义 X.509 证书(将 Java 密钥存储文件 替换为自定义密钥对 InstallDir/etc/host.key )。

3.1.8. 启用 JMX 端口

默认情况下启用 JMX 端口,并通过 JAAS 身份验证进行保护。若要访问 JMX 端口,您必须至少有一个登录凭证配置有一组登录凭证。要连接到 JMX 端口,请打开 JMX 客户端(例如,jconsole)并连接到以下 JMX URI:

service:jmx:rmi:///jndi/rmi://localhost:1099/karaf-root

您还必须向 JMX 客户端提供有效的 JAAS 凭据,才能进行连接。

注意

通常,JMX URI 的尾部的格式为 /karaf-ContainerName。如果将容器名称从 root 更改为其他名称,您必须相应地修改 JMX URI。

3.1.9. 加强 Fuse 控制台端口的安全性

Fuse 控制台已经由 JAAS 身份验证进行保护。要添加 SSL 安全性,请参阅 保护 Undertow HTTP 服务器

第 4 章 将 Apache Karaf 安装为服务

本章介绍了如何使用提供的模板将 Apache Karaf 实例作为系统服务启动。

4.1. 概述

通过使用服务脚本模板,您可以使用特定于操作系统的 init 脚本的帮助运行 Karaf 实例。您可以在 bin/contrib 目录下找到这些模板。

4.2. 运行PERC as a Service

karaf-service.sh 实用程序可帮助您自定义模板。这个实用程序会自动识别操作系统以及默认 init 系统,并生成随时可用的初始化脚本。您还可以通过设置 JAVA_HOME 和几个其他环境变量来自定义脚本,使其适应环境。

生成的脚本由两个文件组成:

  • 初始化脚本
  • init 配置文件

4.3. systemd

karaf-service.sh 程序标识 systemd 时,它会生成三个文件:

  • 用于管理 root Apache Karaf 容器的 systemd 单元文件。
  • systemd 环境文件,其中包含由 root Apache Karaf 容器使用的变量。
  • (不支持) systemd 模板单元文件,以管理 Apache Karaf 子容器。

例如,要为在 /opt/karaf-4 处安装的 Karaf 实例设置服务,为服务提供名称 karaf-4

$ ./karaf-service.sh -k /opt/karaf-4 -n karaf-4
Writing service file "/opt/karaf-4/bin/contrib/karaf-4.service"
Writing service configuration file ""/opt/karaf-4/etc/karaf-4.conf"
Writing service file "/opt/karaf-4/bin/contrib/karaf-4@.service"
$ sudo cp /opt/karaf-4/bin/contrib/karaf-4.service /etc/systemd/system
$ sudo systemctl enable karaf-4.service

4.4. SysV

karaf-service.sh 工具标识 SysV 系统时,它会生成两个文件:

  • 用于管理 root Apache Karaf 容器的初始化脚本。
  • 包含由 root Apache Karaf 容器使用的变量的环境文件。

例如,要为在 /opt/karaf-4 处安装的 Karaf 实例设置服务,为服务提供名称 karaf-4

$ ./karaf-service.sh -k /opt/karaf-4 -n karaf-4
Writing service file "/opt/karaf-4/bin/contrib/karaf-4"
Writing service configuration file "/opt/karaf-4/etc/karaf-4.conf"
$ sudo ln -s /opt/karaf-4/bin/contrib/karaf-4 /etc/init.d/
$ sudo chkconfig karaf-4 on
注意

要在启动时启用服务,请参考您的操作系统 init 指南。

4.5. Solaris SMF

karaf-service.sh 实用程序标识了 Solaris 操作系统时,它会生成一个文件。

例如,要为在 /opt/karaf-4 处安装的 Karaf 实例设置服务,为服务提供名称 karaf-4

$ ./karaf-service.sh -k /opt/karaf-4 -n karaf-4
Writing service file "/opt/karaf-4/bin/contrib/karaf-4.xml"
$ sudo svccfg validate /opt/karaf-4/bin/contrib/karaf-4.xml
$ sudo svccfg import /opt/karaf-4/bin/contrib/karaf-4.xml
注意

生成的 SMF 描述符是临时的,以便您可以只执行一次启动方法。

4.6. Windows

通过 winsw 支持将 Apache Karaf 作为 Windows 服务安装。

要将 Apache Karaf 安装为 Windows 服务,请执行以下步骤:

  1. karaf-service-win.exe 文件重命名为 karaf-4.exe
  2. karaf-service-win.xml 文件重命名为 karaf-4.xml
  3. 根据需要自定义服务描述符。
  4. 使用服务可执行文件来安装、启动和停止服务。

例如:

C:\opt\apache-karaf-4\bin\contrib> karaf-4.exe install
C:\opt\apache-karaf-4\bin\contrib> karaf-4.exe start

4.7. karaf-service.sh Options

您可以将选项指定为命令行选项,也可以通过设置环境变量来指定 karaf-service.sh 实用程序,如下所示:

命令行选项环境变量描述

-k

KARAF_SERVICE_PATH

Karaf 安装路径

-d

KARAF_SERVICE_DATA

Karaf 数据路径(默认为 ${KARAF_SERVICE_PATH}/数据

-c

KARAF_SERVICE_CONF

Karaf 配置文件(默认为 ${KARAF_SERVICE_PATH}/etc/${KARAF_SERVICE_NAME}.conf

-t

KARAF_SERVICE_ETC

glibc etc path(默认为 ${KARAF_SERVICE_PATH}/etc}

-p

KARAF_SERVICE_PIDFILE

Karaf PID 路径(默认为 ${KARAF_SERVICE_DATA}/${KARAF_SERVICE_NAME}.pid

-n

KARAF_SERVICE_NAME

Karaf 服务名称(默认为 karaf

-e

KARAF_ENV

为服务指定环境变量设置 NAME=VALUE (可多次指定)

-u

KARAF_SERVICE_USER

Karaf 用户

-g

KARAF_SERVICE_GROUP

Karaf 组(默认为 ${KARAF_SERVICE_USER}

-l

KARAF_SERVICE_LOG

Karaf 控制台日志(默认为 ${KARAF_SERVICE_DATA}/log/${KARAF_SERVICE_NAME}-console.log

-f

KARAF_SERVICE_TEMPLATE

要使用的模板文件

-x

KARAF_SERVICE_EXECUTABLE

Karaf 可执行文件名称(默认为 karaf fsanitize-capabilitiesmust 支持 守护进程 和停止 命令)

-h

 

帮助信息

第 5 章 构建 OSGi 捆绑包

摘要

本章论述了如何使用 Maven 构建 OSGi 捆绑包。对于构建捆绑包,Maven bundle 插件会扮演重要角色,因为它可让您自动生成 OSGi 捆绑包的标头(否则会是一个繁琐的任务)。Maven archetypes 生成完整的示例项目,也可以为您的捆绑包项目提供一个起点。

5.1. 生成捆绑包项目

5.1.1. 使用 Maven archetypes 生成捆绑包项目

为了帮助您快速启动,您可以调用 Maven archetype 来生成 Maven 项目的初始概述( Maven archetype 与项目向导类似)。以下 Maven archetype 生成一个项目来构建 OSGi 捆绑包。

5.1.2. Apache Camel archetype

Apache Camel OSGi archetype 创建了一个项目,用于构建可部署到 OSGi 容器中的路由。

以下示例演示了如何使用 Maven archetype 命令和 GroupId:ArtifactId: Version:Version 来生成 camel-blueprint 项目。

mvn archetype:generate \
 -DarchetypeGroupId=org.apache.camel.archetypes \
 -DarchetypeArtifactId=camel-archetype-blueprint \
 -DarchetypeVersion=2.23.2.fuse-7_11_1-00015-redhat-00002

运行此命令后,Maven 会提示您指定 GroupIdArtifactId 和版本。

5.1.3. 构建捆绑包

默认情况下,前面的 archetypes 在一个新目录中创建一个项目,其名称与指定的工件 ID ArtifactId 相同。要构建新项目定义的捆绑包,请打开命令提示符,进入项目目录(即包含 pom.xml 文件的目录),并输入以下 Maven 命令:

mvn install

该命令的作用是编译所有 Java 源文件,以在 ArtifactId/target 目录下生成 bundle JAR,然后在本地 Maven 存储库中安装生成的 JAR。

5.2. 修改现有的 Maven 项目

5.2.1. 概述

如果您已有 Maven 项目并想对其进行修改,以便其生成 OSGi 捆绑包,请执行以下步骤:

5.2.2. 将软件包类型改为捆绑包

通过将软件包类型更改为捆绑到项目的 pom.xml 文件中,配置 Maven 以生成 OSGi 捆绑包。将 打包 元素的内容更改为 bundle,如下例所示:

<project ... >
  ...
  <packaging>bundle</packaging>
  ...
</project>

此设置的影响是选择 Maven bundle 插件 maven-bundle-plugin 来为此项目执行打包。但是,此设置本身无效,直到将捆绑包插件显式添加到您的 POM 之前才会生效。

5.2.3. 将捆绑包插件添加到您的 POM

要添加 Maven bundle 插件,请将以下示例 插件 元素复制并粘贴到项目的 pom.xml 文件的 project/build/plugins 部分:

<project ... >
  ...
  <build>
    <defaultGoal>install</defaultGoal>
    <plugins>
      ...
    <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>3.3.0</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Bundle-SymbolicName>${project.groupId}.${project.artifactId}
            </Bundle-SymbolicName>
            <Import-Package>*</Import-Package>
          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

这里的 bundle 插件由 instructions 元素中的设置配置。

5.2.4. 自定义 bundle 插件

有关为 Apache CXF 配置捆绑插件的某些具体建议,请参阅 第 5.3 节 “在捆绑包中打包 Web 服务”

5.2.5. 自定义 JDK 编译器版本

在您的 POM 文件中指定 JDK 版本几乎始终是必需的。如果您的代码使用 Java 语言的任何现代功能,如通用、静态导入等,且您未在 POM 中自定义 JDK 版本,则 Maven 将无法编译源代码。将 JAVA_HOMEPATH 环境变量设置为 JDK 的正确值不足,还必须修改 POM 文件。

要配置您的 POM 文件,使其接受 JDK 1.8 中引入的 Java 语言功能,请将以下 maven-compiler-plugin 插件设置添加到您的 POM(如果不存在它们):

<project ... >
  ...
  <build>
    <defaultGoal>install</defaultGoal>
    <plugins>
      ...
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

5.3. 在捆绑包中打包 Web 服务

5.3.1. 概述

本节介绍如何为 Apache CXF 应用程序修改现有 Maven 项目,以便项目生成适合在红帽 Fuse OSGi 容器中部署的 OSGi 捆绑包。要转换 Maven 项目,您需要修改项目的 POM 文件和项目的蓝图文件(位于 META-INF/spring中)。

5.3.2. 修改 POM 文件以生成捆绑包

要配置 Maven POM 文件来生成捆绑包,您需要进行两种更改:更改 POM 的软件包类型到 捆绑包 ;并将 Maven 捆绑插件添加到您的 POM。详情请查看 第 5.1 节 “生成捆绑包项目”

5.3.3. 必需的导入软件包

要让您的应用程序使用 Apache CXF 组件,您需要将其软件包导入到应用程序的捆绑包中。由于 Apache CXF 中的依赖关系的复杂特性,您无法依赖 Maven 捆绑包插件或 bnd 工具,以自动决定所需的导入。您需要明确声明它们。

您需要将以下软件包导入到您的捆绑包中:

javax.jws
javax.wsdl
javax.xml.bind
javax.xml.bind.annotation
javax.xml.namespace
javax.xml.ws
org.apache.cxf.bus
org.apache.cxf.bus.spring
org.apache.cxf.bus.resource
org.apache.cxf.configuration.spring
org.apache.cxf.resource
org.apache.cxf.jaxws
org.springframework.beans.factory.config

5.3.4. Maven bundle 插件说明示例

例 5.1 “配置强制导入软件包” 展示如何在 POM 中配置 Maven 捆绑插件以导入必需的软件包。必需的导入软件包在 Import-Package 元素内以逗号分隔列表的形式出现。请注意通配符(1)的外观,即,作为列表的最后一个元素。通配符确保扫描当前捆绑包中的 Java 源文件,以发现需要导入哪些附加软件包。

例 5.1. 配置强制导入软件包

<project ... >
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        ...
                        <Import-Package>
                            javax.jws,
                            javax.wsdl,
                            javax.xml.bind,
                            javax.xml.bind.annotation,
                            javax.xml.namespace,
                            javax.xml.ws,
                            org.apache.cxf.bus,
                            org.apache.cxf.bus.spring,
                            org.apache.cxf.bus.resource,
                            org.apache.cxf.configuration.spring,
                            org.apache.cxf.resource,
                            org.apache.cxf.jaxws,
                            org.springframework.beans.factory.config,
                            *
                        </Import-Package>
                        ...
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
    ...
</project>

5.3.5. 添加代码生成插件

Web 服务项目通常需要生成代码。Apache CXF 为 JAX-WS 前端提供两个 Maven 插件,这使您可以将代码生成步骤集成到您的构建中。插件选择取决于您使用 Java 优先方法或 WSDL-first 方法开发您的服务,如下所示:

  • java -first 方法- 使用 cxf-java2ws-plugin 插件。
  • WSDL-first 方法- 使用 cxf-codegen-plugin 插件。

5.3.6. OSGi 配置属性

OSGi 配置管理服务定义了将配置设置传递给 OSGi 捆绑包的机制。您不必使用此服务进行配置,但它通常是配置捆绑包应用程序的最便捷方式。蓝图提供对 OSGi 配置的支持,可让您使用从 OSGi 配置管理员服务获取的值替换 Blueprint 文件中的变量。

有关如何使用 OSGi 配置属性的详情,请参考 第 5.3.7 节 “配置捆绑插件”第 9.6 节 “在功能中添加 OSGi 配置”

5.3.7. 配置捆绑插件

概述

捆绑包插件需要很少的信息才能正常工作。所有所需属性都使用默认设置来生成有效的 OSGi 捆绑包。

虽然您可以使用默认值创建有效的捆绑包,但您可能需要修改某些值。您可以在插件的 instructions 元素中指定大多数属性。

配置属性

一些常用的配置属性有:

设置捆绑包的符号链接

默认情况下,Bundle 插件将 Bundle-SymbolicName 属性的值设置为 groupId + "." + artifactId,其例外情况如下:

  • 如果 groupId 只有一个部分(无点),则返回第一个带有类的软件包名称。

    例如,如果组 Id 是 commons-logging:commons-logging,则捆绑包的符号链接是 org.apache.commons.logging

  • 如果 artifactId 等于 groupId 的最后部分,则使用 groupId

    例如,如果 POM 指定组 ID 和工件 ID 作为 org.apache.maven:maven,则捆绑包的符号链接名为 org.apache.maven

  • 如果 artifactIdgroupId 的最后部分开始,该部分会被删除。

    例如,如果 POM 指定组 ID 和工件 ID 作为 org.apache.maven:maven-core,则捆绑包的符号链接名为 org.apache.maven.core

要为捆绑包符号名称指定您自己的值,在插件的 instructions 元素中添加 Bundle-SymbolicName 子,如 例 5.2 “设置捆绑包的符号链接” 所示。

例 5.2. 设置捆绑包的符号链接

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
     ...
    </instructions>
  </configuration>
</plugin>

设置捆绑包的名称

默认情况下,捆绑包的名称设置为 ${project.name}

要为捆绑包名称指定您自己的值,在插件的 instructions 元素中添加 Bundle-Name 子部分,如 例 5.3 “设置捆绑包的名称” 所示。

例 5.3. 设置捆绑包的名称

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Bundle-Name>JoeFred</Bundle-Name>
     ...
    </instructions>
  </configuration>
</plugin>

设置捆绑包的版本

默认情况下,捆绑包的版本设置为 ${project.version}。所有横线(-)替换为句点(.),数字最多可为四位数。例如,4.2-SNAPSHOT 变为 4.2.0.SNAPSHOT

要为捆绑包版本指定您自己的值,将 Bundle-Version 子添加到插件的 instructions 元素中,如 例 5.4 “设置捆绑包的版本” 所示。

例 5.4. 设置捆绑包的版本

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Bundle-Version>1.0.3.1</Bundle-Version>
     ...
    </instructions>
  </configuration>
</plugin>

指定导出的软件包

默认情况下,OSOS 清单的 Export-Package 列表由您的本地 Java 源代码中的所有软件包(在 src/main/java 下)填充(在 src/main/java下), 默认软件包. 以及包含 .impl.internal 的软件包。

重要

如果您在插件配置中使用 Private-Package 元素,且您没有指定要导出的软件包列表,则默认行为仅包含捆绑包中的 Private-Package 元素中列出的软件包。没有导出软件包。

默认行为可能会导致非常大的软件包,并导出应保持私有的软件包。要更改导出的软件包列表,您可以在插件的 instructions 元素中添加 Export-Package child。

Export-Package 元素指定要包含在捆绑包中的软件包列表,并要导出。可以使用 * 通配符符号指定软件包名称。例如,条目 com.fuse.demo.* 包含项目类路径上以 com.fuse.demo 开头的所有软件包。

您可以指定要排除的软件包,用 ! 前缀。例如,条目 !com.fuse.demo.private 排除软件包 com.fuse.demo.private

当排除软件包时,列表中的条目顺序非常重要。这个列表会根据开始的顺序处理,并忽略后续迭代条目。

例如,要包含以 com.fuse.demo 开头的所有软件包,除了软件包 com.fuse.demo.private 外,请使用以下内容列出软件包:

!com.fuse.demo.private,com.fuse.demo.*

但是,如果您使用 com.fuse.demo.*,!com.fuse.demo.private 列出软件包,那么捆绑包中包含 com.fuse.demo.private,因为它与第一个模式匹配。

指定私有软件包

如果要在导出捆绑包中指定要包含在捆绑包中的软件包列表,您可以在捆绑包插件配置中添加 Private-Package 指令。默认情况下,如果您没有指定 Private-Package 指令,则捆绑包中包含您本地 Java 源中的所有软件包。

重要

如果软件包与 Private-Package 元素和 Export-Package 元素中的条目匹配,则 Export-Package 元素将具有优先权。软件包会添加到捆绑包中并导出。

Private-Package 元素的工作方式与 导出-Package 元素类似,您会指定要包含在捆绑包中的软件包列表。bundle 插件使用列表来查找要包含在捆绑包中的项目的类路径上的所有类。这些软件包打包在捆绑包中,但不导出(除非它们也由 Export-Package 指令选择)。

例 5.5 “在捆绑包中包含私有软件包” 显示在捆绑包中包含私有软件包的配置

例 5.5. 在捆绑包中包含私有软件包

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Private-Package>org.apache.cxf.wsdlFirst.impl</Private-Package>
     ...
    </instructions>
  </configuration>
</plugin>

指定导入的软件包

默认情况下,Bundle 插件使用捆绑包内容引用的所有软件包列表填充 OSGi 清单的 Import-Package 属性。

虽然默认行为通常足以满足大多数项目,但您可能会发现您要导入不会自动添加到列表中的软件包的实例。默认行为也可以导致导入不需要的软件包。

要指定要由捆绑包导入的软件包列表,请将 Import-Package child 添加到插件的 instructions 元素中。软件包列表的语法与 Export-Package 元素和 Private-Package 元素的语法相同。

重要

使用 Import-Package 元素时,插件不会自动扫描捆绑包的内容,以确定是否存在所需的导入。要确保对捆绑包的内容进行了扫描,您必须在软件包列表中放置一个 * 作为最后一个条目。

例 5.6 “指定捆绑包导入的软件包” 显示指定捆绑包导入的软件包的配置

例 5.6. 指定捆绑包导入的软件包

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <configuration>
   <instructions>
     <Import-Package>javax.jws, javax.wsdl, org.apache.cxf.bus, org.apache.cxf.bus.spring, org.apache.cxf.bus.resource, org.apache.cxf.configuration.spring, org.apache.cxf.resource, org.springframework.beans.factory.config, * </Import-Package>
     ...
   </instructions>
  </configuration>
</plugin>

更多信息

有关配置捆绑包插件的详情,请参考:

5.3.8. OSGI configAdmin 文件命名规则

PID 字符串(symbolic-name 语法)允许在 OSGI 规格中允许连字符。但是,连字符由 Apache Felix.fileinstallconfig:edit shell 命令解释,以区分"托管服务"和"托管服务工厂"。因此,建议您不要在 PID 字符串的其他位置使用连字符。

注意

配置文件名称与 PID 和 factory PID 相关。

第 6 章 热部署与手动部署

摘要

Fuse 提供两种不同的方法来部署文件:热部署或手动部署。如果您需要部署一个相关捆绑包的集合,您可以将它们部署为 功能,而不是即时部署(请参阅 第 9 章 部署功能)。

6.1. 热部署

6.1.1. 热部署目录

Fuse 监控 FUSE_HOME/deploy 目录中的文件,热部署在此目录中的所有内容。每次将文件复制到此目录中时,都会在运行时安装并启动。然后,您可以更新或删除 FUSE_HOME/deploy 目录中的文件,并且会自动处理更改。

例如,如果您只构建了捆绑包,则 ProjectDir/target/foo-1.0-SNAPSHOT.jar 您可通过按照如下所示将其复制到 FUSE_HOME/deploy 目录(假设您在 UNIX 平台上工作)来部署此捆绑包:

% cp ProjectDir/target/foo-1.0-SNAPSHOT.jar FUSE_HOME/deploy

6.2. 热取消部署捆绑包

要从热部署目录中取消部署捆绑包,只需从 FUSE_HOME/deploy 目录中删除捆绑包文件 ,而 Apache Karaf 容器正在运行

重要

在容器关闭时,热取消部署机制 无法正常工作。如果关闭 Karaf 容器,请从 FUSE_HOME/deploy 目录删除捆绑包文件,然后重启 Karaf 容器,该捆绑包在重启容器后 不会被 取消部署。

您还可以使用 bundle:uninstall console 命令取消部署捆绑包。

6.3. 手动部署

6.3.1. 概述

您可以通过在 Fuse 控制台中执行命令来手动部署和取消部署捆绑包。

6.3.2. 安装捆绑包

使用 bundle:install 命令,在 OSGi 容器中安装一个或多个捆绑包。这个命令有以下语法:

bundle:install [-s] [--start] [--help] UrlList

其中 UrlList 是一个空格分隔的 URL 列表,用于指定要部署的每个捆绑包的位置。支持以下命令参数:

-s
安装后启动捆绑包。
--start
-s 相同。
--help
显示并解释命令语法。

例如,若要安装和启动捆绑包,ProjectDir/target/foo-1.0-SNAPSHOT.jar 在 Karaf 控制台提示下输入以下命令:

bundle:install -s file:ProjectDir/target/foo-1.0-SNAPSHOT.jar
注意

在 Windows 平台上,您必须小心谨慎,才能在此命令中 对文件 URL 使用正确的语法。详情请查看 第 15.1 节 “文件 URL 处理程序”

6.3.3. 卸载捆绑包

要卸载捆绑包,您必须首先使用 bundle:list 命令获取其捆绑包 ID。然后,您可以使用 bundle:uninstall 命令卸载捆绑包(它会将捆绑包 ID 用作其参数)。

例如,如果您已安装名为 A Camel OSGi Service Unit 的捆绑包,在控制台提示中输入 bundle:list 可能会生成类似如下的输出:

...
[ 181] [Resolved   ] [            ] [       ] [   60] A Camel OSGi Service Unit (1.0.0.SNAPSHOT)

现在,您可以通过输入以下控制台命令使用 ID 181 来卸载捆绑包:

bundle:uninstall 181

6.3.4. 查找捆绑包的 URL 方案

当指定 bundle:install 命令的位置 URL 时,您可以使用 Fuse 支持的任何 URL 方案,其中包括以下方案类型:

6.4. 使用 bundle:watch 自动重新部署捆绑包

在开发环境中,开发人员会不断更改并重建捆绑包,通常需要多次重新安装捆绑包。使用 bundle:watch 命令,您可以指示 Karaf 在本地 Maven 存储库更改时,在它在本地 Maven 存储库中更改时自动重新安装特定的捆绑包。

例如,如果一个特定的 bundle-with bundle ID 751- - 您可以通过输入以下命令启用自动重新部署:

bundle:watch 751

现在,每当您将 Maven 工件重建并安装到本地 Maven 存储库时(例如,通过在 Maven 项目中执行 mvn install ),则 Karaf 容器会自动重新安装更改的 Maven 工件。如需了解更多详细信息,请参阅 Apache Karaf 控制台参考

重要

使用 bundle:watch 命令只适用于开发环境。不建议在生产环境中使用

第 7 章 生命周期管理

7.1. 捆绑包生命周期状态

OSGi 环境中的应用程序受其捆绑包的生命周期约束。捆绑包有六个生命周期状态:

  1. installed - 所有捆绑包都以已安装的状态启动。处于已安装状态的捆绑包正在等待它们的所有依赖项被解决,一旦被解决,捆绑包就会变为已解决的状态。
  2. 已解析 - 当满足以下条件时,捆绑包会移到已解析的状态:

    • 运行时环境满足或超过捆绑包指定的环境。
    • 捆绑包导入的所有软件包均由处于已解析状态的捆绑包公开,或者可以和当前捆绑包同时移到已解析状态。
    • 所有所需的捆绑包都处于已解析状态,也可以与当前捆绑包同时解决。

      重要

      所有应用程序的捆绑包都必须处于已解析状态,然后才能启动应用程序。

      如果上述任何条件满足,则捆绑包将重新移到已安装的状态。例如,当从容器中删除包含导入软件包的捆绑包时,会出现这种情况。

  3. 启动 - 启动状态是已解析状态和主动状态之间的过渡状态。当捆绑包启动时,容器必须为捆绑包创建资源。当提供容器时,容器还调用捆绑包的 start() 方法。
  4. Active - 处于 active 状态的捆绑包可供工作。处于 active 状态的一个捆绑包取决于捆绑包的内容。例如,包含 JAX-WS 服务提供商的捆绑包表示该服务可用于接受请求。
  5. 停止 - 停止状态是活跃状态和已解析状态之间的过渡状态。当停止捆绑包时,容器必须清理捆绑包的资源。当提供容器时,容器还调用捆绑包的 stop() 方法。
  6. unmount - 卸载捆绑包后,它将从已解析的状态移到卸载状态。处于此状态的捆绑包无法转换为已解析的状态或任何其他状态。它必须明确重新安装。

应用程序开发人员最重要的生命周期状态是启动状态和停止状态。应用程序公开的端点在启动状态发布。公布的端点在停止状态停止。

7.2. 安装并解决捆绑包

当使用 bundle:install 命令(不带 -s 标志)安装捆绑包时,内核会安装指定的捆绑包并尝试将其置于已解析状态。如果捆绑包的解析因为某种原因失败(例如,如果其中一个依赖项没有满意),则内核会使捆绑包处于已安装状态。

稍后(例如,安装缺少的依赖项后),您可以尝试通过调用 bundle:resolve 命令将捆绑包移到已解析的状态,如下所示:

bundle:resolve 181

其中 参数(181,在本例中)是您要解析的捆绑包的 ID。

7.3. 启动和停止捆绑包

您可以使用 bundle:start 命令启动一个或多个捆绑包(从已安装的或已解析的状态)。例如,要启动 ID、181、185 和 186 的捆绑包,请输入以下命令:

bundle:start 181 185 186

您可以使用 bundle:stop 命令停止一个或多个捆绑包。例如,要停止带有 ID、181、185 和 186 的捆绑包,请输入以下命令:

bundle:stop 181 185 186

您可以使用 bundle:restart 命令来重启一个或多个捆绑包(即,从启动状态移到已解析状态)。例如,要重启带有 ID、181、185 和 186 的捆绑包,请输入以下命令:

bundle:restart 181 185 186

7.4. 捆绑包启动级别

起始级别 与每个捆绑包相关联。start 级别是一个正整数值,用于控制捆绑要激活/启动的顺序。在具有高级别的捆绑包之前,启动具有最低级别的捆绑包。因此,与起始级别的捆绑包 1 开始,首先启动属于内核的捆绑包,它们往往具有较低的启动级别,因为它们提供运行大多数其他捆绑包的先决条件。

通常,用户捆绑包的开始级别是 60 或更高版本。

7.5. 指定捆绑包的开始级别

使用 bundle:start-level 命令设置特定捆绑包的开始级别。例如,要将捆绑包配置为 ID 为 181,为了使启动级别 70,请输入以下命令:

bundle:start-level 181 70

7.6. 系统启动级别

OSGi 容器本身有与之关联的启动级别,此系统启动级别 决定哪个捆绑包可以活跃且不能:只有启动级别 小于或等于系统启动 级别的捆绑包才可以激活。

要发现当前系统启动级别,在控制台中输入 system:start-level,如下所示:

karaf@root()> system:start-level
Level 100

如果要更改系统启动级别,请为 system:start-level 命令提供新的启动级别作为 system:start-level 命令的参数,如下所示:

system:start-level 200

第 8 章 依赖项故障排除

8.1. 缺少依赖项

当您将 OSGi 捆绑包部署到红帽 Fuse 容器时,会发生最常见的问题是缺少一个或多个依赖项。当您尝试在 OSGi 容器中解决捆绑包时,通常会作为启动该捆绑包的一个副作用。捆绑包无法解析(或启动),并且日志记录了 ClassNotFound 错误(查看日志,请使用 log:display 控制台命令或查看 FUSE_HOME/data/log 目录中的日志文件)。

缺少的依赖项的基本原因有两个:容器中没有安装所需的功能或捆绑包;或者您的捆绑包的 Import-Package 标头不完整。

8.2. 未安装所需的功能或捆绑包

在尝试解决您的捆绑包前,您的捆绑包所需的所有功能和捆绑包必须已在 OSGi 容器中安装。特别是,因为 Apache Camel 具有模块化架构,即将每个组件作为单独的功能安装,因此易于安装其中一个需要的组件。

注意

考虑将捆绑包打包为一个功能。使用一个功能,您可以将捆绑包与其所有依赖项一起打包,从而确保它们都同时安装。详情请查看 第 9 章 部署功能

8.3. import-Package 标头不完整

如果已经安装了所有必需的功能和捆绑包,您仍然会收到 ClassNotFound 错误,这意味着捆绑包 MANIFEST.MF 文件中的 Import-Package 标头不完整。在生成您的捆绑包的 Import-Package 标头时,maven-bundle-plugin (请参阅 第 5.2 节 “修改现有的 Maven 项目”)是一个很好的帮助,但您应该注意以下几点:

  • 确保将通配符 * 包括在 Maven bundle 插件配置的 Import-Package 元素中。通配符指示插件扫描您的 Java 源代码,并自动生成软件包依赖项列表。
  • Maven bundle 插件 无法 找出动态依赖项。例如,如果您的 Java 代码明确调用类加载类来动态加载类,则捆绑插件不会考虑它,而所需的 Java 软件包不会在生成的 Import-Package 标头中列出。
  • 如果您定义了 Blueprint XML 文件(例如在 OSGI-INF/blueprint 目录中),则 在运行时自动解析 来自 Blueprint XML 文件的任何依赖项。

8.4. 如何跟踪缺失的依赖项

要跟踪缺少的依赖项,请执行以下步骤:

  1. 使用 bundle:diag console 命令。这将提供有关为什么您的捆绑包不活跃的信息。有关使用信息,请参阅 Apache Karaf 控制台参考
  2. 执行快速检查,以确保在 OSGi 容器中真正安装所有必需的捆绑包和功能。您可以使用 bundle:list 来检查已安装的哪些捆绑包,以及 features:list 检查是否已安装哪些功能。
  3. 使用 bundle:install console 命令安装(但不启动)您的捆绑包。例如:

    karaf@root()> bundle:install MyBundleURL
  4. 使用 bundle:dynamic-import console 命令,在刚安装的捆绑包上启用动态导入。例如,如果捆绑包的捆绑包 ID 是 218,您可以通过输入以下命令在该捆绑包上启用动态导入:

    karaf@root()> bundle:dynamic-import 218

    此设置允许使用容器中已安装的 任何 捆绑包(基于 Import-Package 标头)来解析依赖项。这不会 记住用于正常部署,因为它会绕过版本检查:您可以轻松地获取错误的软件包版本,从而导致应用程序出现故障。

  5. 现在,您应该能够解析您的捆绑包。例如,如果您的捆绑包 ID 是 218,请输入 followng console 命令:

    karaf@root()> bundle:resolve 218
  6. 假设您的捆绑包现已解决(使用 bundle:list检查捆绑包状态),您可以使用 package:imports 命令获取所有软件包的完整列表。例如,如果您的捆绑包 ID 是 218,请输入以下命令:

    karaf@root()> package:imports -b 218

    您应该在控制台窗口中看到一个依赖软件包列表:

    Package                              │ Version       │ Optional   │ ID  │ Bundle Name
    ─────────────────────────────────────┼───────────────┼────────────┼─────┼──────────────────────────────────
    org.apache.jasper.servlet            │ [2.2.0,3.0.0) │ resolved   │ 217 │ org.ops4j.pax.web.pax-web-runtime
    org.jasypt.encryption.pbe            │               │ resolved   │ 217 │ org.ops4j.pax.web.pax-web-runtime
    org.ops4j.pax.web.jsp                │ [7.0.0,)      │ resolved   │ 217 │ org.ops4j.pax.web.pax-web-runtime
    org.ops4j.pax.web.service.spi.model  │ [7.0.0,)      │            │ 217 │ org.ops4j.pax.web.pax-web-runtime
    org.ops4j.pax.web.service.spi.util   │ [7.0.0,)      │            │ 217 │ org.ops4j.pax.web.pax-web-runtime
    ...
  7. 解包您的捆绑包 JAR 文件,并查看 META-INF/MANIFEST.MF 文件中 Import-Package 标头中列出的软件包。将这个列表与上一步中找到的软件包列表进行比较。现在,编译清单中 Import-Package 标头中缺少的软件包列表,并将这些软件包名称添加到项目的 POM 文件的 Maven 捆绑插件配置的 Import-Package 元素中。
  8. 要取消动态导入选项,您必须从 OSGi 容器中卸载旧的捆绑包。例如,如果您的捆绑包 ID 是 218,请输入以下命令:

    karaf@root()> bundle:uninstall 218
  9. 现在,您可以使用导入的软件包的更新列表重建捆绑包,并在 OSGi 容器中进行测试。

addurl :experimental: :toc: :toclevels: 4 :numbered:

第 9 章 部署功能

摘要

因为应用程序和其他工具通常包含多个 OSGi 捆绑包,因此通常可以方便地将相互独立或相关的捆绑包聚合成较大的部署单元。因此,Red Hat Fuse 提供了可扩展的部署单元,它可让您在一个步骤中部署多个捆绑包(以及可选的依赖)。

9.1. 创建功能

9.1.1. 概述

本质上,通过将新功能元素添加到一种特殊 XML 文件(称为 功能存储库)来创建一个功能要创建功能,请执行以下步骤:

9.2. 创建自定义功能存储库

如果您还没有定义自定义功能存储库,您可以按照如下所示创建一个。在您的文件系统中为功能存储库选择一个方便的位置,例如 C:\Projects\features.xml- 并使用您最喜欢的文本编辑器将以下行添加到其中:

<?xml version="1.0" encoding="UTF-8"?>
<features name="CustomRepository">
</features>

您必须通过设置 name 属性来指定存储库的名称 CustomRepository

注意

与 Maven 存储库或 OBR 不同,功能存储库 不提供 捆绑包的存储位置。功能存储库只是存储对捆绑包的引用聚合。捆绑包本身存储在其他位置(例如,文件系统中或 Maven 存储库中)。

9.3. 为自定义功能存储库添加功能

要向自定义功能存储库添加功能,请插入一个新的 feature 元素作为根 功能 元素的子项。您必须通过插入捆绑包子元素来为功能指定名称,并且可以列出属于该功能的任何 捆绑包。例如,添加名为 example-camel-bundle 的功能,其中包含单一捆绑包 C:\Projects\camel-bundle\camel-bundle-1.0-SNAPSHOT.jar,添加功能元素:

<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
  <feature name="example-camel-bundle">
    <bundle>file:C:/Projects/camel-bundle/target/camel-bundle-1.0-SNAPSHOT.jar</bundle>
  </feature>
</features>

bundle 元素的内容可以是任何有效的 URL,提供捆绑包的位置(请参阅 第 15 章 URL 处理程序)。您可以选择在 feature 元素上指定一个 version 属性,为该功能分配非零版本(然后将版本指定为 features:install 命令的一个可选参数)。

要检查功能服务是否已成功解析新功能条目,请输入以下命令:

JBossFuse:karaf@root> features:refreshurl
JBossFuse:karaf@root> features:list
...
[uninstalled] [0.0.0                 ] example-camel-bundle                 MyFeaturesRepo
...

features:list 命令通常会生成比较长的功能列表,但您应当能够通过滚动列表来查找新功能的条目(本例中为 example-camel-bundle)。features:refreshurl 命令强制内核重新读取所有功能存储库:如果您没有发布这个命令,则内核不会了解您对任何存储库所做的任何最新更改(特别是,新功能不会出现在列表中)。

为了避免通过长功能列表进行滚动,您可以按如下方式对 example-camel-bundle 功能进行 grep

JBossFuse:karaf@root> features:list | grep example-camel-bundle
[uninstalled] [0.0.0                 ] example-camel-bundle                 MyFeaturesRepo

其中 grep 命令(标准 UNIX 模式匹配实用程序)内置在 shell 中,因此此命令也可以用于 Windows 平台。

9.4. 将本地存储库 URL 添加到功能服务中

为了让新功能存储库可供 Apache Karaf 使用,您必须使用 features:addurl console 命令添加功能存储库。例如,要使存储库的内容 C:\Projects\features.xml 提供给内核,您需要输入以下命令:

features:addurl file:C:/Projects/features.xml

其中 features:addurl 的参数可以使用任何支持的 URL 格式来指定(请参阅 第 15 章 URL 处理程序)。

您可以通过输入 features:listUrl console 命令来检查存储库的 URL 是否已正确注册,以获取所有已注册功能存储库 URL 的完整列表,如下所示:

JBossFuse:karaf@root> features:listUrl
file:C:/Projects/features.xml
mvn:org.apache.ode/ode-jbi-karaf/1.3.3-fuse-01-00/xml/features
mvn:org.apache.felix.karaf/apache-felix-karaf/1.2.0-fuse-01-00/xml/features

9.5. 在功能中添加依赖功能

如果您的功能依赖于其他功能,您可以通过添加功能元素作为原始 功能 元素的子元素来指定这些依赖项。每个子 功能 元素包含当前功能所依赖的功能的名称。当您使用依赖功能部署功能时,依赖项机制会检查是否在容器中安装依赖功能。如果没有,依赖项机制会自动安装缺少的依赖项(以及任何递归依赖项)。

例如,对于自定义 Apache Camel 功能( example-camel-bundle ),您可以指定它所依赖的标准 Apache Camel 功能。这有优势,现在可成功部署并运行应用程序,即使 OSGi 容器没有预部署所需的功能。例如,您可以使用 Apache Camel 依赖项定义 example-camel-bundle 功能,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
  <feature name="example-camel-bundle">
    <bundle>file:C:/Projects/camel-bundle/target/camel-bundle-1.0-SNAPSHOT.jar</bundle>
    <feature version="7.11.1.fuse-7_11_1-00013-redhat-00003">camel-core</feature>
    <feature version="7.11.1.fuse-7_11_1-00013-redhat-00003">camel-spring-osgi</feature>
  </feature>
</features>

指定 version 属性是可选的。当存在时,它可让您选择指定版本的功能。

9.6. 在功能中添加 OSGi 配置

如果您的应用程序使用 OSGi 配置管理员 服务,您可以使用功能定义中的 config 子元素指定该服务的配置设置。例如,要指定 prefix 属性的值为 MyTransform,请将以下配置子元素添加到您的功能配置中:

<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
  <feature name="example-camel-bundle">
    <config name="org.fusesource.fuseesb.example">
      prefix=MyTransform
    </config>
  </feature>
</features>

其中 config 元素的 name 属性指定属性设置 的持久 ID (其中持久性 ID 充当属性名称的名称范围)。config 元素的内容的解析方式与 Java 属性文件 相同。

config 元素中的设置可以被 InstallDir/etc 目录中的 Java 属性文件中的设置覆盖,该文件以持久 ID 命名,如下所示:

InstallDir/etc/org.fusesource.fuseesb.example.cfg

例如,在实践中使用上述配置属性的示例,请考虑以下 Blueprint XML 文件来访问 OSGi 配置属性:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">

    <!-- osgi blueprint property placeholder -->
    <cm:property-placeholder id="placeholder"
                             persistent-id="org.fusesource.fuseesb.example">
        <cm:default-properties>
            <cm:property name="prefix" value="DefaultValue"/>
        </cm:default-properties>
    </cm:property-placeholder>

    <bean id="myTransform" class="org.fusesource.fuseesb.example.MyTransform">
      <property name="prefix" value="${prefix}"/>
    </bean>

</blueprint>

当此蓝图 XML 文件部署到 example-camel-bundle 捆绑包中时,属性引用 ${prefix} 将替换为值 MyTransform,由功能存储库中的 config 元素指定。

9.7. 自动部署 OSGi 配置

通过将 configfile 元素添加到功能,您可以确保在安装该功能时,DOSGi 配置文件被添加到 InstallDir/etc 目录中。这意味着您可以方便地安装一个功能及其关联的配置。

例如,如果 org.fusesource.fuseesb.example.cfg 配置文件被归档到 mvn:org.fusesource.fuseesb.example/configadmin/1.0/cfg 的 Maven 存储库中,您可以通过将以下元素添加到功能来部署配置文件:

<configfile finalname="etc/org.fusesource.fuseesb.example.cfg">
  mvn:org.fusesource.fuseesb.example/configadmin/1.0/cfg
</configfile>

第 10 章 部署功能

10.1. 概述

您可以使用以下方法之一部署功能:

  • 使用 features:install 在控制台中安装。
  • 使用热部署。
  • 修改引导配置(首次引导!)。

10.2. 在控制台中安装

创建功能(通过在功能存储库中添加条目和注册功能存储库)后,使用 features:install console 命令部署该功能相对容易。例如,要部署 example-camel-bundle 功能,请输入以下命令对控制台命令:

JBossFuse:karaf@root> features:refreshurl
JBossFuse:karaf@root> features:install example-camel-bundle

建议您在调用 features:install 前调用 features:refreshurl 命令,以便在内核尚未获取的功能存储库中对功能进行了任何最新更改。features:install 命令将功能名称用作其参数(以及可选的功能版本作为其第二个参数)。

注意

功能使用扁平命名空间。因此,在命名功能时要小心,以避免与现有功能进行名称冲突。

10.3. 在控制台中卸载

要卸载功能,请按如下方式调用 feature :uninstall 命令:

JBossFuse:karaf@root> features:uninstall example-camel-bundle
注意

卸载后,在您调用 features:list 但没有状态将标记为 [uninstalled] 时,该功能仍会显示。

10.4. 热部署

只需将功能存储库文件复制到 InstallDir/deploy 目录中,即可热部署功能存储库中 的所有功能

由于您不太可能一次性热部署整个功能存储库,因此通常更方便地定义减少功能存储库或功能 描述符,后者只引用您要部署的功能。功能描述符与功能存储库完全相同,但会以不同的样式编写。区别在于,功能描述符仅包含对来自功能存储库的现有功能的引用。

例如,您可以定义一个功能描述符来加载 example-camel-bundle 功能,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<features name="CustomDescriptor">
  <repository>RepositoryURL</repository>
  <feature name="hot-example-camel-bundle">
    <feature>example-camel-bundle</feature>
  </feature>
</features>

repository 元素指定自定义功能存储库(您可使用 第 15 章 URL 处理程序中描述的任何 URL 格式)的位置。功能 hot-example-camel-bundle 只是对现有功能( example-camel-bundle )的引用。

10.5. 热取消部署功能文件

要从热部署目录中取消部署功能文件,只需从 InstallDir/deploy 目录删除功能文件 ,而 Apache Karaf 容器正在运行

重要

在容器关闭时,热取消部署机制 无法正常工作。如果关闭 Karaf 容器,请从 deploy/ 中删除功能文件,然后重启 Karaf 容器,在重启容器后 不会 取消部署该功能(但可以使用 features:uninstall console 命令手动取消部署功能)。

10.6. 在引导配置中添加功能

如果您想为在多个主机上置备 Apache Karaf 副本,您可能有兴趣向引导配置添加功能,这决定了在 Apache Karaf 首次引导时安装的功能集合。

安装目录中的配置文件 /etc/org.apache.karaf.features.cfg 包括了以下设置:

...
#
# Comma separated list of features repositories to register by default
#
featuresRepositories = \
    mvn:org.apache-extras.camel-extra.karaf/camel-extra/2.21.0.fuse-000032-redhat-2/xml/features, \
    mvn:org.apache.karaf.features/spring-legacy/4.2.0.fuse-000191-redhat-1/xml/features, \
    mvn:org.apache.activemq/artemis-features/2.4.0.amq-710008-redhat-1/xml/features, \
    mvn:org.jboss.fuse.modules.patch/patch-features/7.0.0.fuse-000163-redhat-2/xml/features, \
    mvn:org.apache.karaf.features/framework/4.2.0.fuse-000191-redhat-1/xml/features, \
    mvn:org.jboss.fuse/fuse-karaf-framework/7.0.0.fuse-000163-redhat-2/xml/features, \
    mvn:org.apache.karaf.features/standard/4.2.0.fuse-000191-redhat-1/xml/features, \
    mvn:org.apache.karaf.features/enterprise/4.2.0.fuse-000191-redhat-1/xml/features, \
    mvn:org.apache.camel.karaf/apache-camel/2.21.0.fuse-000055-redhat-2/xml/features, \
    mvn:org.apache.cxf.karaf/apache-cxf/3.1.11.fuse-000199-redhat-1/xml/features, \
    mvn:io.hawt/hawtio-karaf/2.0.0.fuse-000145-redhat-1/xml/features

#
# Comma separated list of features to install at startup
#
featuresBoot = \
    instance/4.2.0.fuse-000191-redhat-1, \
    cxf-commands/3.1.11.fuse-000199-redhat-1, \
    log/4.2.0.fuse-000191-redhat-1, \
    pax-cdi-weld/1.0.0, \
    camel-jms/2.21.0.fuse-000055-redhat-2, \
    ssh/4.2.0.fuse-000191-redhat-1, \
    camel-cxf/2.21.0.fuse-000055-redhat-2, \
    aries-blueprint/4.2.0.fuse-000191-redhat-1, \
    cxf/3.1.11.fuse-000199-redhat-1, \
    cxf-http-undertow/3.1.11.fuse-000199-redhat-1, \
    pax-jdbc-pool-narayana/1.2.0, \
    patch/7.0.0.fuse-000163-redhat-2, \
    cxf-rs-description-swagger2/3.1.11.fuse-000199-redhat-1, \
    feature/4.2.0.fuse-000191-redhat-1, \
    camel/2.21.0.fuse-000055-redhat-2, \
    jaas/4.2.0.fuse-000191-redhat-1, \
    camel-jaxb/2.21.0.fuse-000055-redhat-2, \
    camel-paxlogging/2.21.0.fuse-000055-redhat-2, \
    deployer/4.2.0.fuse-000191-redhat-1, \
    diagnostic/4.2.0.fuse-000191-redhat-1, \
    patch-management/7.0.0.fuse-000163-redhat-2, \
    bundle/4.2.0.fuse-000191-redhat-1, \
    kar/4.2.0.fuse-000191-redhat-1, \
    camel-csv/2.21.0.fuse-000055-redhat-2, \
    package/4.2.0.fuse-000191-redhat-1, \
    scr/4.2.0.fuse-000191-redhat-1, \
    maven/4.2.0.fuse-000191-redhat-1, \
    war/4.2.0.fuse-000191-redhat-1, \
    camel-mail/2.21.0.fuse-000055-redhat-2, \
    fuse-credential-store/7.0.0.fuse-000163-redhat-2, \
    framework/4.2.0.fuse-000191-redhat-1, \
    system/4.2.0.fuse-000191-redhat-1, \
    pax-http-undertow/6.1.2, \
    camel-jdbc/2.21.0.fuse-000055-redhat-2, \
    shell/4.2.0.fuse-000191-redhat-1, \
    management/4.2.0.fuse-000191-redhat-1, \
    service/4.2.0.fuse-000191-redhat-1, \
    camel-undertow/2.21.0.fuse-000055-redhat-2, \
    camel-blueprint/2.21.0.fuse-000055-redhat-2, \
    camel-spring/2.21.0.fuse-000055-redhat-2, \
    hawtio/2.0.0.fuse-000145-redhat-1, \
    camel-ftp/2.21.0.fuse-000055-redhat-2, \
    wrap/2.5.4, \
    config/4.2.0.fuse-000191-redhat-1, \
    transaction-manager-narayana/5.7.2.Final

这个配置文件有两个属性:

  • featuresRepositories-comma separated separated features repositories 列表,以便在启动时加载。
  • 功能Boot-comma 在启动时安装的功能列表。

您可以修改配置来自定义在 Fuse 启动时安装的功能。如果计划使用预安装的功能发布 Fuse,您也可以修改这个配置文件。

重要

这个添加功能的方法仅在特定的 Apache Karaf 实例引导时有效。之后对 featuresRepositories 设置所做的任何更改都会被忽略,即使重启容器也是如此。

但是,您可以强制容器恢复到其初始状态,方法是删除 InstallDir/data/cache 的完整内容(从而丢失了所有容器的自定义设置)。

第 11 章 部署 Plain JAR

摘要

将应用部署到 Apache Karaf 的替代方法是使用普通 JAR 文件。这些通常是 不包含任何部署元数据的库。普通 JAR 既不是 WAR,也不是一种 OSGi 捆绑包。

如果普通 JAR 作为捆绑包的依赖项而发生,您必须将捆绑包标头添加到 JAR 中。如果 JAR 公开一个公共 API,通常是将现有的 JAR 转换为捆绑包,使 JAR 能够与其他捆绑包共享。使用开源 Bnd 工具,使用本章中的说明自动执行转换过程。

有关 Bnd 工具的更多信息,请参阅 Bnd 工具网站

11.1. 使用 wrap Scheme 转换 JAR

概述

您可以使用 wrap: protocol(可以和任何现有 URL 格式)将 JAR 转换为捆绑包。wrap: protocol 基于 Bnd 工具程序。

语法

wrap: protocol 具有以下基本语法:

wrap:LocationURL

wrap: protocol 可以为找到 JAR 的任何 URL 加上前缀。查找部分 URL LocationURL 用于获取普通 JAR 和 wrap: 协议的 URL 处理程序,然后将 JAR 自动转换为捆绑包。

注意

wrap: protocol 还支持更协作的语法,它可让您通过在 URL 中指定 Bnd 属性文件或在 URL 中指定单独的 Bnd 属性来自定义转换。但是,嵌套: 协议与默认设置一起使用。

默认属性

wrap: protocol 基于 Bnd 工具程序,因此它使用完全相同的默认属性来生成捆绑包,就像 Bnd 一样。

wrap and install

以下示例演示了如何使用单个控制台命令从远程 Maven 存储库下载纯 commons-logging JAR,将其动态转换为 OSGi 捆绑包,然后在 OSGi 容器中启动它:

karaf@root> bundle:install -s wrap:mvn:commons-logging/commons-logging/1.1.1

参考

嵌套 协议由 Pax 项目 提供,后者是各种开源 OSGi 实用程序的 umbrella 项目。有关 wrap: protocol 的完整文档,请查看 Wrap Protocol 参考页面。

第 12 章 OSGi 服务

摘要

OSGi 核心框架定义了 OSGi 服务层,它提供了一个简单机制,通过将 Java 对象注册为 OSGi 服务 registry 中的服务来进行交互。OSGi 服务模型的优势在于,任何 Java 对象都可以作为服务来提供:没有特定限制、继承规则或注解必须应用于服务类。本章论述了如何使用 OSGi Blueprint 容器部署 OSGi 服务。

12.1. Blueprint 容器

摘要

Blueprint 容器是一个依赖项注入框架,简化了与 OSGi 容器的交互。Blueprint 容器支持使用基于配置的方法,使用 OSGi 服务注册表(例如,提供标准的 XML 元素用于导入和导出 OSGi 服务)。

12.1.1. 蓝图配置

在 JAR 文件中的蓝图文件位置

相对于 bundle JAR 文件的根目录,Blueprint 配置文件的标准位置如下:

OSGI-INF/blueprint

此目录下带有后缀 .xml 的文件解释为 Blueprint 配置文件;换句话说,任何与模式匹配的文件 OSGI-INF/blueprint/*.xml

Maven 项目中的蓝图文件位置

在 Maven 项目 ProjectDir 上下文中,Blueprint 配置文件的标准位置如下:

ProjectDir/src/main/resources/OSGI-INF/blueprint

蓝图命名空间和 root 元素

蓝图配置元素与以下 XML 命名空间关联:

http://www.osgi.org/xmlns/blueprint/v1.0.0

蓝图配置的根元素是 蓝图,因此蓝图 XML 配置文件通常具有以下概述:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  ...
</blueprint>
注意

蓝图 根元素中,不需要使用 xsi:schemaLocation 属性指定 Blueprint 模式的位置,因为 schema 位置已已知在 Blueprint 框架中。

蓝图清单配置

Blueprint 配置的一些方面由 JAR 清单文件中 META-INF/MANIFEST.MF 中的标头控制,如下所示:

自定义蓝图文件位置

如果您需要将 Blueprint 配置文件放在非标准位置(即 OSGI-INF/blueprint/*.xml以外的其他位置),您可以用逗号分隔在清单文件中 Bundle-Blueprint 标头中的其他位置列表:

Bundle-Blueprint: lib/account.xml, security.bp, cnf/*.xml

必需的依赖项

默认情况下,OSOS 服务的依赖项是强制的(虽然通过将 availability 属性设置为参考元素或一个 参考 列表 元素上的 可选 )可以进行更改。将依赖项声明为强制性意味着捆绑包无法正常运行,且这个依赖关系必须始终可用。

通常,当蓝图容器被初始化时,它会通过 宽限期,在这期间它尝试解析所有强制的依赖项时。如果在此时间内无法解决强制依赖关系(默认超时为 5 分钟),则容器初始化将中止且不会启动捆绑包。以下设置可附加到 Bundle-SymbolicName 清单标头中,以配置宽限期:

blueprint.graceperiod
如果为 true (默认),则启用了宽限期,并且 Blueprint 容器在初始化过程中会等待一个强制依赖项解析;如果为 false,则会跳过宽限期,容器不会检查是否已解决强制依赖关系。
blueprint.timeout
以毫秒为单位指定宽限期超时。默认值为 300000(5 分钟)。

例如,要启用 10 秒的宽限期,您可以在清单文件中定义以下 Bundle-SymbolicName 标头:

Bundle-SymbolicName: org.fusesource.example.osgi-client;
 blueprint.graceperiod:=true;
 blueprint.timeout:= 10000

Bundle-SymbolicName 标头的值是一个分号隔开的列表,其中第一个项目是实际捆绑包符号名称,第二个项目是 蓝图。graceperiod:=true 来启用宽限期,第三项,blueprint.timeout:= 10000 指定了 10 秒超时。

12.1.2. 定义服务 Bean

概述

Blueprint 容器允许您使用 bean 元素实例化 Java 类。您可以以这种方式创建所有主应用程序对象。特别是,您可以使用 bean 元素创建代表 OSGi 服务实例的 Java 对象。

蓝图 Bean 元素

Blueprint bean 元素在 Blueprint 架构命名空间 http://www.osgi.org/xmlns/blueprint/v1.0.0 中定义。

Bean 示例

以下示例演示了如何使用 Blueprint 的 Bean 来创建几种不同类型的 bean

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <bean id="label" class="java.lang.String">
    <argument value="LABEL_VALUE"/>
  </bean>

  <bean id="myList" class="java.util.ArrayList">
    <argument type="int" value="10"/>
  </bean>

  <bean id="account" class="org.fusesource.example.Account">
    <property name="accountName" value="john.doe"/>
    <property name="balance" value="10000"/>
  </bean>

</blueprint>

其中 ,最后一个 bean 示例引用的帐户 类可以定义如下:

package org.fusesource.example;

public class Account
{
    private String accountName;
    private int balance;

    public Account () { }

    public void setAccountName(String name) {
        this.accountName = name;
    }

    public void setBalance(int bal) {
        this.balance = bal;
    }
    ...
}

参考信息

有关定义 Blueprint Bean 的详情,请参考以下参考:

12.1.3. 使用属性配置蓝图

概述

这部分论述了如何使用在 Camel 上下文以外的文件中保存的属性配置 Blueprint。

配置 Blueprint Bean

蓝图 Bean 可以通过使用可通过从外部文件使用属性放置的变量进行配置。您需要声明 ext 命名空间,并在 Blueprint xml 中添加 属性占位符 an。使用 Property-Placeholder bean 声明您的属性文件的位置到 Blueprint。

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0">

    <ext:property-placeholder>
      <ext:location>file:etc/ldap.properties</ext:location>
    </ext:property-placeholder>
    ...
    <bean ...>
        <property name="myProperty" value="${myProperty}" />
    </bean>
</blueprint>

属性拥有者配置选项 的规格可在 http://aries.apache.org/schemas/blueprint-ext/blueprint-ext.xsd 找到。

12.2. 导出服务

概述

这部分论述了如何将 Java 对象导出到 OSGi 服务 registry,从而使它可作为服务来访问 OSGi 容器中的其他捆绑包。

使用单个接口导出

要在一个接口名称下将服务导出到 OSGi 服务 registry,请使用 ref 属性定义引用相关服务 bean 的服务元素,并使用 interface 属性指定已发布的 接口

例如,您可以使用 例 12.1 “使用单一接口进行服务导出示例” 中显示的 Blueprint 配置代码,在 org.fusesource.example.Account 接口名称下导出 SavingsAccountImpl 类的实例。

例 12.1. 使用单一接口进行服务导出示例

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>

  <service ref="savings" interface="org.fusesource.example.Account"/>

</blueprint>

其中 ref 属性指定对应的 bean 实例的 ID,而 interface 属性指定服务在 OSGi 服务注册表中注册的公共 Java 接口的名称。本例中使用的类别和接口如下所示 例 12.2 “帐户类和接口示例”

例 12.2. 帐户类和接口示例

package org.fusesource.example

public interface Account { ... }

public interface SavingsAccount { ... }

public interface CheckingAccount { ... }

public class SavingsAccountImpl implements SavingsAccount
{
    ...
}

public class CheckingAccountImpl implements CheckingAccount
{
    ...
}

使用多个接口导出

要在多个接口名称下将服务导出到 OSGi 服务 registry,请使用 ref 属性定义引用相关服务 bean 的服务元素,并使用 interfaces 子元素指定已发布的接口。

例如,您可以在公共 Java 接口列表下导出 SavingsAccountImpl 类的实例,org.fusesource.example.Accountorg.fusesource.example.SavingsAccount,使用以下 Blueprint 配置代码:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>
  <service ref="savings">
    <interfaces>
      <value>org.fusesource.example.Account</value>
      <value>org.fusesource.example.SavingsAccount</value>
    </interfaces>
  </service>
  ...
</blueprint>
注意

interface 属性和 interfaces 元素无法同时在同一 服务 元素中使用。您必须使用一个或另一个。

使用自动导出导出

如果要在其实施的公共 Java 接口下将服务导出到 OSGi 服务 registry,那么使用 auto-export 属性即可轻松完成此操作。

例如,要在所有实施的公共接口下导出 SavingsAccountImpl 类的实例,请使用以下 Blueprint 配置代码:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>
  <service ref="savings" auto-export="interfaces"/>
  ...
</blueprint>

auto-export 属性的 interfaces 值表示 Blueprint 应该注册通过 节省sAccountImpl 实施的所有公共接口。auto-export 属性可以具有以下有效值:

disabled
禁用自动导出。这是默认值。
interfaces
将该服务注册到所有实施的公共 Java 接口。
class-hierarchy
将服务注册到自己的类型(class)下,并在除 Object 类外的所有超级用户(su-types(super-classes)下注册。
all-classes
class-hierarchy 选项一样,包括所有已实施的公共 Java 接口。

设置服务属性

OSGi 服务 registry 还允许您将服务 属性 与注册的服务相关联。然后,服务的客户端可以使用服务属性来搜索或过滤服务。要将服务属性与导出服务关联,请添加 service-properties 子元素,其中包含一个或多个 Bean:entry 元素(每个服务属性的一个 Bean:entry 元素)。

例如,要将 bank.name 字符串属性与节省的帐户服务相关联,您可以使用以下蓝图配置:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:beans="http://www.springframework.org/schema/beans"
           ...>
  ...
  <service ref="savings" auto-export="interfaces">
    <service-properties>
      <beans:entry key="bank.name" value="HighStreetBank"/>
    </service-properties>
  </service>
  ...
</blueprint>

银行.name 字符串属性具有值 HighStreetBank。可以对字符串以外的类型定义服务属性:即,支持原语类型、数组和集合。有关如何定义这些类型的详情,请参阅 Spring 参考指南 中的 控制 Advertised Properties 设置

注意

属于 Blueprint 命名空间 的条目 元素。在 Spring 的蓝图实施中的 Bean:entry 元素是非标准。

默认服务属性

使用 service 元素导出服务时可能会自动设置两个服务属性,如下所示:

  • os.service.blueprint.compname-is 始终设置为服务的 bean 元素的 id,除非被嵌入(即,bean 定义为 服务 元素的子元素)。内联 Bean 始终是匿名的。
  • service.ranking-is 会自动设置,如果 ranking 属性为零。

指定 ranking 属性

如果捆绑包在服务 registry 中查找一个服务并找到多个匹配的服务,您可以使用等级确定是否返回哪些服务。该规则是,每当查找匹配多个服务时,返回具有最高等级的服务。服务等级可以是任何非负的整数,其中 0 是默认值。您可以通过设置 service 元素 上的 ranking 属性来指定服务等级:

<service ref="savings" interface="org.fusesource.example.Account" ranking="10"/>

指定注册监听程序

如果要跟踪服务注册和取消注册事件,您可以定义一个 注册和取消注册事件通知的注册监听程序 回调。要定义注册监听程序,请将 registration-listener 子元素添加到 服务 元素中。

例如,以下 blueprint 配置定义了一个监听器 bean, listenerBean,它被 registration-listener 元素引用,以便在 帐户 服务注册或取消注册时收到回调:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" ...>
  ...
  <bean id="listenerBean" class="org.fusesource.example.Listener"/>

  <service ref="savings" auto-export="interfaces">
    <registration-listener
        ref="listenerBean"
        registration-method="register"
        unregistration-method="unregister"/>
  </service>
  ...
</blueprint>

如果 registration-listener 元素的 ref 属性引用侦听器的 idregistration-method 属性指定接收注册回调的监听程序方法的名称,而 unregistration-method 属性指定接收非注册回调的监听程序方法的名称。

以下 Java 代码显示了 Listener 类的示例定义,接收注册和取消注册事件的通知:

package org.fusesource.example;

public class Listener
{
    public void register(Account service, java.util.Map serviceProperties) {
        ...
    }

    public void unregister(Account service, java.util.Map serviceProperties) {
        ...
    }
}

方法名称、注册和 取消注册 分别由 registration-methodunregistration-method 属性指定。这些方法的签名必须符合以下语法:

  • 第一个参数- 任何可从服务对象类型分配的 T 类型。换句话说,服务类的任何超级类型类或任何由服务类实施的接口。此参数包含服务实例,除非 service bean 声明了要进行设计 的范围 (在本例中为 null 时(当范围为 null 时,没有服务实例在注册时没有可用)。
  • 第二个方法参数- 必须为 java.util.Map 类型或 java.util.Dictionary 类型。此映射包含与此服务注册关联的服务属性。

12.3. 导入服务

概述

本节论述了如何获取和使用被导出到 OSGi 服务 registry 的 OSGi 服务的引用。您可以使用 引用 元素或 参考列表 元素导入 OSGi 服务。reference 元素适合访问 无状态 服务,而 参考列表 元素则适合访问 有状态 服务。

管理服务引用

支持获取 OSGi 服务参考的以下模型:

参考管理器

reference manager 实例由 Blueprint 参考 元素创建。此元素返回单个服务引用,它是访问 无状态 服务的首选方法。图 12.1 “对无状态服务的引用” 展示了使用参考管理器访问无状态服务的模型概述。

图 12.1. 对无状态服务的引用

部署简单的 svc 01

客户端 Blueprint 容器中的 Bean 使用代理对象( 提供的对象 )注入,该对象由 OSGi 服务注册表的服务对象( 后备服务)支持。这个模型通过以下方式明确利用无状态服务可交换的事实:

  • 如果发现多个服务实例与 参考 元素中的条件匹配,则参考管理器可以任意选择其中一个作为后备实例(因为可以交换它们)。
  • 如果后备服务消失,则参考管理器可以立即切换为使用同一类型的其它可用服务之一。因此,不能保证,从一种方法调用下一个方法,代理会保持连接到同一后端服务。

客户端和后备服务之间的合同 是无状态的,客户端 不得 假定它始终与同一服务实例通信。如果没有可用的匹配的服务实例,代理会在引发 ServiceUnavailable 异常前等待特定的时间。可以通过设置 reference 元素上的 timeout 属性来配置超时的长度。

参考列表管理器

Blueprint reference-list 元素会创建一个参考列表管理器 实例。此元素返回服务引用列表,它是访问 有状态 服务的首选方法。图 12.2 “Stateful 服务的参考列表” 展示了使用参考列表管理器访问有状态服务的模型概述。

图 12.2. Stateful 服务的参考列表

部署简单的 svc 02

客户端蓝图容器中的 Bean 通过 java.util.List 对象( 提供的对象)注入,其中包含代理对象列表。每个代理都由 OSGi 服务 registry 中的唯一服务实例来支持。与无状态模型不同,支持服务 不被视为可交换的。实际上,列表中每个代理的生命周期都与对应的支持服务的生命周期紧密关联:当服务在 OSGi 注册表中注册时,会同步创建并添加到代理列表中;在服务从 OSGi 注册表中取消注册时,相应的代理会同步从代理列表中删除。

代理及其支持服务之间的合同 是有状态的,因此当它在特定代理上调用方法时,客户端可能会假定它始终 与同一 后端服务通信。但是,如果后备服务不可用,但可能会在代理变得过时时,该后备服务可能会变得不可用。在过时的代理上调用方法的任何尝试都会生成 ServiceUnavailable 异常。

通过接口(无状态)匹配.

获取 状态 服务引用最简单的方法是使用 参考 元素上的 interface 属性来指定要匹配的 接口。如果 interface 属性值是该服务的超类型,或者属性值是由服务实施的 Java 接口( interface 属性可指定 Java 类或 Java 接口),则服务被认为是匹配的。

例如,若要引用无状态保存 帐户 服务(请参阅 例 12.1 “使用单一接口进行服务导出示例”),请按如下所示定义一个 参考 元素:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <reference id="savingsRef"
             interface="org.fusesource.example.SavingsAccount"/>

  <bean id="client" class="org.fusesource.example.client.Client">
    <property name="savingsAccount" ref="savingsRef"/>
  </bean>

</blueprint>

如果 参考 元素创建了一个参考管理器,其 ID 为 savingsRef。要使用被引用的服务,请将 savings Refan 注入到您的其中一个客户端类中,如下所示。

注入客户端类的 bean 属性可以是可在保存账户中分配的任何类型。例如,您可以按照以下方式定义 Client 类:

package org.fusesource.example.client;

import org.fusesource.example.SavingsAccount;

public class Client {
    SavingsAccount savingsAccount;

    // Bean properties
    public SavingsAccount getSavingsAccount() {
        return savingsAccount;
    }

    public void setSavingsAccount(SavingsAccount savingsAccount) {
        this.savingsAccount = savingsAccount;
    }
    ...
}

通过接口(stateful)进行匹配.

获取 有状态 服务引用的最简单方法是通过利用 reference-list 元素上的 interface 属性来指定要匹配的接口。然后,参考列表管理器会获取所有服务的列表,其接口 属性值是服务的超类型,或者由服务实施的 Java 接口( 接口 属性可以指定 Java 类或 Java 接口)。

例如,若要引用有状态 savings sAccount 服务(请参阅 例 12.1 “使用单一接口进行服务导出示例”),请定义 参考列表 元素,如下所示:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <reference-list id="savingsListRef"
                  interface="org.fusesource.example.SavingsAccount"/>

  <bean id="client" class="org.fusesource.example.client.Client">
    <property name="savingsAccountList" ref="savingsListRef"/>
  </bean>

</blueprint>

其中 reference-list 元素会创建一个参考列表管理器及 ID, savingsListRef。要使用引用的服务列表,请将 savings ListRefan 引用注入到您的其中一个客户端类中,如下所示。

默认情况下,savingsAccountList bean 属性是一个服务对象列表(例如 java.util.List<SavingsAccount>)。您可以按照以下方法定义客户端类:

package org.fusesource.example.client;

import org.fusesource.example.SavingsAccount;

public class Client {
    java.util.List<SavingsAccount> accountList;

    // Bean properties
    public java.util.List<SavingsAccount> getSavingsAccountList() {
        return accountList;
    }

    public void setSavingsAccountList(
                    java.util.List<SavingsAccount> accountList
    ) {
        this.accountList = accountList;
    }
    ...
}

根据接口和组件名称匹配

要匹配 无状态 服务的接口和组件名称(bean ID),请指定 参考 元素上的 interface 属性和 component-name 属性,如下所示:

<reference id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           component-name="savings"/>

要匹配 有状态 服务的接口和组件名称(bean ID),请同时指定 reference-list 元素上的 interface 属性和 component-name 属性,如下所示:

<reference-list id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           component-name="savings"/>

使用过滤器匹配服务属性

您可以通过匹配过滤器的服务属性来选择服务。过滤器通过引用元素或 reference -list 元素上的 filter 属性来指定。filter 属性的值必须是 LDAP 过滤器表达式。例如,要定义与 bank.name 服务属性等于 HighStreetBank 时匹配的过滤器,您可以使用以下 LDAP 过滤器表达式:

(bank.name=HighStreetBank)

要匹配两个服务属性值,您可以使用 和 结合使用表达式和逻辑 。例如,要要求 foo 属性等于 FooValue,而 bar 属性等于 BarValue,您可以使用以下 LDAP 过滤器表达式:

(&(foo=FooValue)(bar=BarValue))

有关 LDAP 过滤器表达式的完整语法,请参阅 OSGi 核心规格的 3.2.7 节

过滤器也可以与 接口和 组件名称 设置结合使用,在这种情况下,所有指定条件都需要匹配。

例如,若要将 无状态 服务保存 类型匹配,其 银行 服务属性等于 HighStreetBank,您可以定义一个 参考 元素,如下所示:

<reference id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           filter="(bank.name=HighStreetBank)"/>

要匹配 有状态的 服务 保存账户 类型,银行.name 服务属性等于 HighStreetBank,您可以定义 参考列表 元素,如下所示:

<reference-list id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           filter="(bank.name=HighStreetBank)"/>

指定是否强制(必需)或可选

默认情况下,LOSOS 服务的引用被假定为强制(请参阅 必需的依赖项)。通过在元素上设置 availability 属性,可以自定义参考元素的依赖关系行为或 reference -list 元素。

availability 属性有两个可能的值:

  • 强制 (默认)意味着在普通的 Blueprint 容器初始化过程中 必须解决 依赖项
  • 可选,这意味着在初始化过程中 不需要 解析依赖项。

以下 参考 元素示例显示了如何明确声明引用是一个强制依赖项:

<reference id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           availability="mandatory"/>

指定引用监听程序

例如,若要应对 OSGi 环境的动态性质(例如,如果您声明了一些服务引用)具有 可选 可用性,在将后备服务绑定到注册表并且其未绑定时,跟踪服务通常很有用。要接收服务绑定和取消绑定事件的通知,您可以将 reference-listener 元素定义为参考元素或 reference -list 元素的子项。

例如,以下 Blueprint 配置演示了如何将引用监听程序定义为 ID,savingsRef:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <reference id="savingsRef"
             interface="org.fusesource.example.SavingsAccount"
             >
    <reference-listener bind-method="onBind" unbind-method="onUnbind">
      <bean class="org.fusesource.example.client.Listener"/>
    </reference-listener>
  </reference>

  <bean id="client" class="org.fusesource.example.client.Client">
    <property name="savingsAcc" ref="savingsRef"/>
  </bean>

</blueprint>

上述配置将 org.fusesource.example.client.Listener 类型的实例注册为侦听 bindunbind 事件的回调。每当 savingsRef 引用管理器的后备服务绑定或未绑定时,都会生成事件。

以下示例显示了 Listener 类的实现示例:

package org.fusesource.example.client;

import org.osgi.framework.ServiceReference;

public class Listener {

    public void onBind(ServiceReference ref) {
        System.out.println("Bound service: " + ref);
    }

    public void onUnbind(ServiceReference ref) {
        System.out.println("Unbound service: " + ref);
    }

}

方法名称 onBindonUnbind 分别通过 bind-methodunbind-method 属性指定。这两个回调方法都使用 org.osgi.framework.ServiceReference 参数。

12.4. 发布 OSGi 服务

12.4.1. 概述

本节介绍如何在 OSGi 容器中生成、构建和部署简单的 OSGi 服务。该服务是一个简单的 Hello World Java 类,并且 OSGi 配置是使用 Blueprint 配置文件定义的。

12.4.2. 先决条件

要使用 Maven Quickstart archetype 生成项目,您必须满足以下条件:

  • Maven 安装- Maven 是一个来自 Apache 的免费开源构建工具。您可以从 http://maven.apache.org/download.html 下载最新版本(最小为 2.0.9)。
  • 互联网连接-whilst 执行构建,Maven 会动态搜索外部存储库,并即时下载所需的工件。要使此任务正常工作,构建 机器必须 连接到互联网。

12.4.3. 生成 Maven 项目

maven-archetype- Quickstart archetype 创建一个通用 Maven 项目,然后您可以根据您需要的任何用途进行自定义。要使用协调( org.fusesource.example:osgi-service )生成 Maven 项目,请输入以下命令:

mvn archetype:create
-DarchetypeArtifactId=maven-archetype-quickstart
-DgroupId=org.fusesource.example
-DartifactId=osgi-service

此命令的结果是目录 ProjectDir/osgi-service,包含所生成项目的文件。

注意

请注意 ,不要为您的工件选择一个组 ID,该 ID 与现有产品的组 ID 冲突!这可能会导致项目的软件包和现有产品中的软件包与来自现有产品的软件包之间的冲突(因为组 ID 通常被用作项目 Java 软件包名称的根目录)。

12.4.4. 自定义 POM 文件

您必须自定义 POM 文件才能生成 OSGi 捆绑包,如下所示:

  1. 按照 第 5.1 节 “生成捆绑包项目” 中描述的 POM 自定义步骤操作。
  2. 在 Maven bundle 插件的配置,修改捆绑包指令以导出 org.fusesource.example.service 软件包,如下所示:

    <project ... >
      ...
      <build>
        ...
        <plugins>
          ...
          <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
              <instructions>
                <Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName>
            <Export-Package>org.fusesource.example.service</Export-Package>
              </instructions>
            </configuration>
          </plugin>
        </plugins>
      </build>
      ...
    </project>

12.4.5. 编写服务接口

创建 ProjectDir/osgi-service/src/main/java/org/fusesource/example/service 子目录。在这个目录中,使用您首选的文本编辑器创建文件 HelloWorldSvc.java,并将代码从 例 12.3 “The HelloWorldSvc Interface” 添加到其中。

例 12.3. The HelloWorldSvc Interface

package org.fusesource.example.service;

public interface HelloWorldSvc
{
    public void sayHello();
}

12.4.6. 编写服务类

创建 ProjectDir/osgi-service/src/main/java/org/fusesource/example/service/impl 子目录。在这个目录中,使用您首选的文本编辑器创建文件 HelloWorldSvcImpl.java,然后将代码从 例 12.4 “The HelloWorldSvcImpl Class” 添加到其中。

例 12.4. The HelloWorldSvcImpl Class

package org.fusesource.example.service.impl;

import org.fusesource.example.service.HelloWorldSvc;

public class HelloWorldSvcImpl implements HelloWorldSvc {

    public void sayHello()
    {
        System.out.println( "Hello World!" );
    }

}

12.4.7. 编写 Blueprint 文件

Blueprint 配置文件是一个 XML 文件,存储在类路径上的 OSGI-INF/blueprint 目录下。要在项目中添加蓝图文件,首先创建以下子目录:

ProjectDir/osgi-service/src/main/resources
ProjectDir/osgi-service/src/main/resources/OSGI-INF
ProjectDir/osgi-service/src/main/resources/OSGI-INF/blueprint

其中 src/main/resources 是所有 JAR 资源的标准 Maven 位置。此目录下的资源文件将自动打包在生成的捆绑包 JAR 的 root 范围内。

例 12.5 “用于导出服务的蓝图文件” 显示了一个示例 Blueprint 文件,该文件使用 bean 元素创建 HelloWorldSvc bean,然后使用 service 元素将 bean 导出为 OSGi 服务

ProjectDir/osgi-service/src/main/resources/OSGI-INF/blueprint 目录下,使用您首选的文本编辑器创建文件 config.xml,并从 例 12.5 “用于导出服务的蓝图文件” 添加 XML 代码。

例 12.5. 用于导出服务的蓝图文件

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <bean id="hello" class="org.fusesource.example.service.impl.HelloWorldSvcImpl"/>

  <service ref="hello" interface="org.fusesource.example.service.HelloWorldSvc"/>

</blueprint>

12.4.8. 运行服务捆绑包

要安装并运行 osgi-service 项目,请执行以下步骤:

  1. 构建项目- 打开命令提示并将目录更改为 ProjectDir/osgi-service。使用以下命令构建演示:

    mvn install

    如果此命令成功运行,则 ProjectDir/osgi-service/target 目录应包含捆绑包文件 osgi-service-1.0-SNAPSHOT.jar

  2. 在 Red Hat Fuse 控制台中安装 并启动 osgi-service 捆绑包,请输入以下命令:

    Jkaraf@root()> bundle:install -s file:ProjectDir/osgi-service/target/osgi-service-1.0-SNAPSHOT.jar

    其中 ProjectDir 是包含 Maven 项目的目录,而 -s 标志会指示容器立即启动捆绑包。例如,如果您的项目目录是 Windows 机器上的 C:\Projects,则使用以下命令:

    karaf@root()> bundle:install -s file:C:/Projects/osgi-service/target/osgi-service-1.0-SNAPSHOT.jar
    注意

    在 Windows 机器中,请注意如何对 文件 URL 进行格式化,以了解 文件 URL 处理程序所了解的语法详情,请参考 第 15.1 节 “文件 URL 处理程序”

  3. 检查该服务是否已创建- 以检查捆绑包是否已成功启动,请输入以下命令:

    karaf@root()> bundle:list

    在这个列表中的某个位置,您应该会看到 osgi-service 捆绑包的行,例如:

    [ 236] [Active     ] [Created     ] [       ] [   60] osgi-service (1.0.0.SNAPSHOT)

12.5. 访问 OSGi 服务

12.5.1. 概述

本节介绍如何在 OSGi 容器中生成、构建和部署简单的 OSGi 客户端。客户端在 OSGi 注册表中找到一个简单的 Hello World 服务,并调用它上的 sayHello() 方法。

12.5.2. 先决条件

要使用 Maven Quickstart archetype 生成项目,您必须满足以下条件:

  • Maven 安装- Maven 是一个来自 Apache 的免费开源构建工具。您可以从 http://maven.apache.org/download.html 下载最新版本(最小为 2.0.9)。
  • 互联网连接-whilst 执行构建,Maven 会动态搜索外部存储库,并即时下载所需的工件。要使此任务正常工作,构建 机器必须 连接到互联网。

12.5.3. 生成 Maven 项目

maven-archetype- Quickstart archetype 创建一个通用 Maven 项目,然后您可以根据您需要的任何用途进行自定义。要使用协调( org.fusesource.example:osgi-client )生成 Maven 项目,请输入以下命令:

mvn archetype:create
-DarchetypeArtifactId=maven-archetype-quickstart
-DgroupId=org.fusesource.example
-DartifactId=osgi-client

此命令的结果是目录 ProjectDir/osgi-client,其中包含生成的项目的文件。

注意

请注意 ,不要为您的工件选择一个组 ID,该 ID 与现有产品的组 ID 冲突!这可能会导致项目的软件包和现有产品中的软件包与来自现有产品的软件包之间的冲突(因为组 ID 通常被用作项目 Java 软件包名称的根目录)。

12.5.4. 自定义 POM 文件

您必须自定义 POM 文件才能生成 OSGi 捆绑包,如下所示:

  1. 按照 第 5.1 节 “生成捆绑包项目” 中描述的 POM 自定义步骤操作。
  2. 由于客户端使用 HelloWorldSvc Java 接口(在 osgi-service 捆绑包中定义),因此需要对 osgi-service 捆绑包添加 Maven 依赖项。假设 osgi-service 捆绑包的 Maven 协调为 org.fusesource.example:osgi-service:1.0-SNAPSHOT,您应该在客户端的 POM 文件中添加以下依赖关系:

    <project ... >
      ...
      <dependencies>
        ...
        <dependency>
            <groupId>org.fusesource.example</groupId>
            <artifactId>osgi-service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
      </dependencies>
      ...
    </project>

12.5.5. 编写 Blueprint 文件

要将 Blueprint 文件添加到客户端项目,请首先创建以下子目录:

ProjectDir/osgi-client/src/main/resources
ProjectDir/osgi-client/src/main/resources/OSGI-INF
ProjectDir/osgi-client/src/main/resources/OSGI-INF/blueprint

ProjectDir/osgi-client/src/main/resources/OSGI-INF/blueprint 目录下,使用您首选的文本编辑器创建文件 config.xml,并从 例 12.6 “用于导入服务的蓝图文件” 添加 XML 代码。

例 12.6. 用于导入服务的蓝图文件

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <reference id="helloWorld"
        interface="org.fusesource.example.service.HelloWorldSvc"/>

  <bean id="client"
        class="org.fusesource.example.client.Client"
        init-method="init">
    <property name="helloWorldSvc" ref="helloWorld"/>
  </bean>

</blueprint>

其中 参考 元素会创建一个参考管理器,该管理器在 OSGi 注册表中找到 HelloWorldSvc 类型的服务。bean 元素会创建一个 Client 类的实例,并注入服务引用作为 bean 属性 helloWorldSvc。此外,init-method 属性指定在 bean 初始化阶段调用 Client.init() 方法(即,在服务引用注入客户端 bean 后)。

12.5.6. 编写客户端类

ProjectDir/osgi-client/src/main/java/org/fusesource/example/client 目录下,使用您首选的文本编辑器创建文件 Client.java,并从 例 12.7 “Client Class” 添加 Java 代码。

例 12.7. Client Class

package org.fusesource.example.client;

import org.fusesource.example.service.HelloWorldSvc;

public class Client {
    HelloWorldSvc helloWorldSvc;

    // Bean properties
    public HelloWorldSvc getHelloWorldSvc() {
        return helloWorldSvc;
    }

    public void setHelloWorldSvc(HelloWorldSvc helloWorldSvc) {
        this.helloWorldSvc = helloWorldSvc;
    }

    public void init() {
        System.out.println("OSGi client started.");
        if (helloWorldSvc != null) {
            System.out.println("Calling sayHello()");
            helloWorldSvc.sayHello();  // Invoke the OSGi service!
        }
    }

}

Client 类为 helloWorldS vcan 属性定义一个 getter 和 setter 方法,它可以通过注入来接收 Hello World 服务的引用。init() 方法在 bean 初始化阶段调用,在属性注入后,这通常可以在此方法范围内调用 Hello World 服务。

12.5.7. 运行客户端捆绑包

要安装并运行 osgi-client 项目,请执行以下步骤:

  1. 构建项目- 打开命令提示并将目录更改为 ProjectDir/osgi-client。使用以下命令构建演示:

    mvn install

    如果此命令成功运行,则 ProjectDir/osgi-client/target 目录应包含捆绑包文件 osgi-client-1.0-SNAPSHOT.jar

  2. 在 Red Hat Fuse 控制台中安装 并启动 osgi-service 捆绑包,请输入以下命令:

    karaf@root()> bundle:install -s file:ProjectDir/osgi-client/target/osgi-client-1.0-SNAPSHOT.jar

    其中 ProjectDir 是包含 Maven 项目的目录,而 -s 标志会指示容器立即启动捆绑包。例如,如果您的项目目录是 Windows 机器上的 C:\Projects,则使用以下命令:

    karaf@root()> bundle:install -s file:C:/Projects/osgi-client/target/osgi-client-1.0-SNAPSHOT.jar
    注意

    在 Windows 机器中,请注意如何对 文件 URL 进行格式化,以了解 文件 URL 处理程序所了解的语法详情,请参考 第 15.1 节 “文件 URL 处理程序”

  3. 客户端输出-f 客户端捆绑包成功启动,您应该在控制台中立即看到类似如下的输出:

    Bundle ID: 239
    OSGi client started.
    Calling sayHello()
    Hello World!

12.6. 与 Apache Camel 集成

12.6.1. 概述

Apache Camel 提供了使用 Bean 语言调用 OSGi 服务的简单方法。每当 Apache Camel 应用程序部署到 OSGi 容器时,这个功能都会自动可用,且不需要特殊配置。

12.6.2. registry 链

当将 Apache Camel 路由部署到 OSGi 容器时,CamelContext 会自动设置 registry 链以解析 Bean 实例:registry 链由 OSGi 注册表组成,然后是 Blueprint 注册表。现在,如果您尝试引用特定的 bean 类或 bean 实例,registry 会按如下方式解析 bean:

  1. 首先查找 OSGi 注册表中的 bean。如果指定了类名称,请尝试将其与 OSGi 服务的接口或类匹配。
  2. 如果在 OSGi 注册表中找不到匹配项,请重新回退到 Blueprint 注册表中。

12.6.3. OSGi 服务接口示例

考虑由以下 Java 接口定义的 OSGi 服务,它定义了单一方法 getGreeting()

package org.fusesource.example.hello.boston;

public interface HelloBoston {
    public String getGreeting();
}

12.6.4. 服务导出示例

在定义实现 HelloBoston OSGi 服务的捆绑包时,您可以使用以下 Blueprint 配置导出该服务:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <bean id="hello" class="org.fusesource.example.hello.boston.HelloBostonImpl"/>

  <service ref="hello" interface="org.fusesource.example.hello.boston.HelloBoston"/>

</blueprint>

假设 HelloBoston 接口通过 HelloBostonImpl 类实施(未显示)。

12.6.5. 从 Java DSL 调用 OSGi 服务

部署包含 HelloBoston OSGi 服务的捆绑包后,您可以使用 Java DSL 从 Apache Camel 应用程序调用该服务。在 Java DSL 中,您可以通过 Bean 语言调用 OSGi 服务,如下所示:

from("timer:foo?period=5000")
  .bean(org.fusesource.example.hello.boston.HelloBoston.class, "getGreeting")
  .log("The message contains: ${body}")

bean 命令中,第一个参数是 OSGi 接口或类,它必须与从 OSGi 服务捆绑包导出的接口匹配。第二个参数是您要调用的 bean 方法的名称。有关 bean 命令语法的完整详情,请参阅 Apache Camel 开发指南 Bean 集成

注意

当您使用此方法时,IOSGi 服务会被隐式导入。在这种情况下,不需要 显式导入 OSGi 服务。

12.6.6. 从 XML DSL 调用 OSGi 服务

在 XML DSL 中,您还可以使用 Bean 语言调用 HelloBoston OSGi 服务,但语法稍有不同。在 XML DSL 中,您可以使用 method 元素通过 Bean 语言调用 OSGi 服务,如下所示:

<beans ...>
  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
      <from uri="timer:foo?period=5000"/>
      <setBody>
          <method ref="org.fusesource.example.hello.boston.HelloBoston" method="getGreeting"/>
      </setBody>
      <log message="The message contains: ${body}"/>
    </route>
  </camelContext>
</beans>
注意

当您使用此方法时,IOSGi 服务会被隐式导入。在这种情况下,不需要 显式导入 OSGi 服务。

第 13 章 使用 JMS 代理部署

摘要

Fuse 7.11 不提供默认的内部代理,但设计为与四个外部 JMS 代理进行接口。

Fuse 7.11 容器包含受支持的外部代理的代理客户端库。

有关在 Fuse 7.11 上可用的外部代理、客户端和 Camel 组件组合的更多信息,请参阅支持的配置。https://access.redhat.com/articles/310603

13.1. AMQ 7 快速入门

提供了快速入门来演示使用 AMQ 7 代理的应用程序设置和部署。

下载快速入门

您可从 Fuse Software Downloads 页面安装所有快速入门。

将下载的 zip 文件的内容提取到本地文件夹,例如:名为 Quickstart 的文件夹。

设置快速入门

  1. 导航到 快速入门/camel/camel-jms 文件夹。
  2. 输入 mvn clean install 来构建 quickstart。
  3. 将文件 org.ops4j.connectionfactory-amq7.cfg/camel/camel-jms/src/main 目录复制到 Fuse 安装中的 FUSE_HOME/etc 目录。验证其内容是否正确代理 URL 和凭证。默认情况下,代理 URL 设置为 AMQ 7 的 CORE 协议的 tcp://localhost:61616。凭证设置为 admin/admin。更改这些详情以适应外部代理。
  4. 通过在 Linux 或 Windows 上运行 bin\fuse.bat 上运行 ./bin/fuse.bat 来启动 Fuse。
  5. 在 Fuse 控制台中输入以下命令:

    feature:install pax-jms-pool artemis-jms-client camel-blueprint camel-jms
    
    install -s mvn:org.jboss.fuse.quickstarts/camel-jms/${project.version}

    当部署捆绑包时,Fuse 将为您提供捆绑包 ID。

  6. 输入 log:display 以查看启动日志信息。检查以确保捆绑包已部署成功。
12:13:50.445 INFO [Blueprint Event Dispatcher: 1] Attempting to start Camel Context jms-example-context
12:13:50.446 INFO [Blueprint Event Dispatcher: 1] Apache Camel 2.21.0.fuse-000030 (CamelContext: jms-example-context) is starting
12:13:50.446 INFO [Blueprint Event Dispatcher: 1] JMX is enabled
12:13:50.528 INFO [Blueprint Event Dispatcher: 1] StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
12:13:50.553 INFO [Blueprint Event Dispatcher: 1] Route: file-to-jms-route started and consuming from: file://work/jms/input
12:13:50.555 INFO [Blueprint Event Dispatcher: 1] Route: jms-cbr-route started and consuming from: jms://queue:incomingOrders?transacted=true
12:13:50.556 INFO [Blueprint Event Dispatcher: 1] Total 2 routes, of which 2 are started

运行快速入门

  1. 当 Camel 路由运行时,将创建 /camel/camel-jms/work/jms/input 目录。将 /camel/camel-jms/src/main/data 目录中的文件复制到 /camel/camel-jms/work/input 目录中。
  2. 复制到 …​/src/main/data 文件中的文件是订购文件。等待一分钟,然后检查 /camel/camel-jms/work/jms/output 目录。文件将根据目的地的国家/地区排序为独立目录:

    • order1.xmlorder2.xmlorder4.xml in /camel/camel-jms/work/jms/outputs/
    • order3.xmlorder5.xml/camel/camel-jms/work/jms/output/us
    • order6.xml in /camel/camel-jms/work/jms/output/fr
  3. 使用 log:display 查看日志信息:
Receiving order order1.xml
Sending order order1.xml to another country
Done processing order1.xml
  1. Camel 命令将显示上下文的详细信息:

使用 camel:context-list 显示上下文详情:

Context               Status              Total #       Failed #     Inflight #   Uptime
-------               ------              -------       --------     ----------   ------
jms-example-context   Started                  12              0              0   3 minutes

使用 camel:route-list 在上下文中显示 Camel 路由:

Context               Route               Status              Total #       Failed #     Inflight #   Uptime
-------               -----               ------              -------       --------     ----------   ------
jms-example-context   file-to-jms-route   Started                   6              0              0   3 minutes
jms-example-context   jms-cbr-route       Started                   6              0              0   3 minutes

使用 camel:route-info 显示交换统计信息:

karaf@root()> camel:route-info jms-cbr-route jms-example-context
Camel Route jms-cbr-route
    Camel Context: jms-example-context
    State: Started
    State: Started

Statistics
    Exchanges Total: 6
    Exchanges Completed: 6
    Exchanges Failed: 0
    Exchanges Inflight: 0
    Min Processing Time: 2 ms
    Max Processing Time: 12 ms
    Mean Processing Time: 4 ms
    Total Processing Time: 29 ms
    Last Processing Time: 4 ms
    Delta Processing Time: 1 ms
    Start Statistics Date: 2018-01-30 12:13:50
    Reset Statistics Date: 2018-01-30 12:13:50
    First Exchange Date: 2018-01-30 12:19:47
    Last Exchange Date: 2018-01-30 12:19:47

13.2. 使用 ROLES 核心客户端

Artemis 核心客户端可用于连接到外部代理,而非 qpid-jms-client

使用 ROLES 核心客户端进行连接

  1. 要启用 6.2 核心客户端,可启动 Fuse。导航到 FUSE_HOME 目录,然后在 Linux 或 bin\fuse.bat 中输入 ./bin/fuse.bat。
  2. 使用以下命令,将 ROLES 客户端添加为 功能:install artemis-core-client
  3. 编写代码时,您需要使用连接工厂将 Camel 组件连接。

导入连接工厂:

import org.apache.qpid.jms.JmsConnectionFactory;

设置连接:

ConnectionFactory connectionFactory = new JmsConnectionFactory("amqp://localhost:5672");
      try (Connection connection = connectionFactory.createConnection()) {

第 14 章 故障转移部署

摘要

红帽 Fuse 使用简单的锁定文件系统或 JDBC 锁定机制提供故障切换功能。在这两种情况下,容器级锁定系统都允许捆绑包加载到二级内核实例中,以便提供更快的故障转移性能。

14.1. 使用简单锁定文件系统

概述

首次启动 Red Hat Fuse 时,会在安装目录的根目录中创建锁定文件。您可以通过设置主实例失败的主(secondary)系统,将锁定传递给位于同一主机上的次要实例。

配置锁定文件系统

要配置锁定文件故障切换部署,请编辑主和二级安装中的 etc/system.properties 文件,使其包含 例 14.1 “锁定文件故障切换配置” 中的属性。

例 14.1. 锁定文件故障切换配置

karaf.lock=true
karaf.lock.class=org.apache.karaf.main.SimpleFileLock
karaf.lock.dir=PathToLockFileDirectory
karaf.lock.delay=10000
  • regex.lock- 指定锁定文件是否被写入。
  • Karaf.lock.class- 表明 Java 类实施锁定。对于简单的文件锁定,它应该总是是 org.apache.karaf.main.SimpleFileLock
  • Karaf.lock.dir-spec 表示将锁定文件写入的目录。对于主安装和二级安装,这 必须相同
  • Karaf.lock.delay-specifies,以毫秒为单位,尝试重新分配锁定之间的延迟。

14.2. 使用 JDBC 锁定系统

概述

JDBC 锁定机制主要用于在单独的机器上存在红帽 Fuse 实例的故障转移部署。

在这种情况下,主实例会在由数据库托管的锁定表中有一个锁定。如果主实例丢失锁定,则等待的辅助进程获得对锁定表的访问,并完全启动其容器。

在类路径中添加 JDBC 驱动程序

在 JDBC 锁定系统中,JDBC 驱动程序需要位于主/secondary设置中每个实例的类路径上。在类路径中添加 JDBC 驱动程序,如下所示:

  1. 将 JDBC 驱动程序 JAR 文件复制到每个 Red Hat Fuse 实例的 ESBInstallDir/lib/ext 目录中。
  2. 修改 bin/karaf start 脚本,使其在 CLASSPATH 变量中包含 JDBC 驱动程序 JAR。

    例如,如果为 JDBC JAR 文件 JDBCJarFile.jar,您可以按如下所示修改起始脚本(在 *NIX 操作系统上):

        ...
        # Add the jars in the lib dir
        for file in "$KARAF_HOME"/lib/karaf*.jar
        do
            if [ -z "$CLASSPATH" ]; then
                CLASSPATH="$file"
            else
                CLASSPATH="$CLASSPATH:$file"
            fi
        done
        CLASSPATH="$CLASSPATH:$KARAF_HOME/lib/JDBCJarFile.jar"
    注意

    如果您要添加 MySQL 驱动程序 JAR 或 PostgreSQL 驱动程序 JAR,您必须用 karaf- 前缀加上前缀来重命名 driver JAR。否则,Apache Karaf 将挂起,日志表明 Apache Karaf 无法找到该驱动程序。

配置 JDBC 锁定系统

要配置 JDBC 锁定系统,请更新主/次要部署中每个实例的 etc/system.properties 文件,如下所示

例 14.2. JDBC 锁定文件配置

karaf.lock=true
karaf.lock.class=org.apache.karaf.main.lock.DefaultJDBCLock
karaf.lock.level=50
karaf.lock.delay=10000
karaf.lock.jdbc.url=jdbc:derby://dbserver:1527/sample
karaf.lock.jdbc.driver=org.apache.derby.jdbc.ClientDriver
karaf.lock.jdbc.user=user
karaf.lock.jdbc.password=password
karaf.lock.jdbc.table=KARAF_LOCK
karaf.lock.jdbc.clustername=karaf
karaf.lock.jdbc.timeout=30

在示例中,如果不存在名为 sample 的数据库,则会创建名为 sample 的数据库。获取锁定表的第一个红帽 Fuse 实例是主实例。如果与数据库的连接丢失,则主实例会尝试正常关闭,允许次要实例在恢复数据库服务时成为主实例。之前的主实例需要手动重启。

在 Oracle 中配置 JDBC 锁定

如果您在 JDBC 锁定方案中使用 Oracle 作为数据库,则 etc/system.properties 文件中的 karaf.lock.class 属性必须指向 org.apache.karaf.main.lock.main.Oracle JDBCLock

否则,将 system.properties 文件配置为常规设置,如下所示:

例 14.3. Oracle 的 JDBC 锁定文件配置

karaf.lock=true
karaf.lock.class=org.apache.karaf.main.lock.OracleJDBCLock
karaf.lock.jdbc.url=jdbc:oracle:thin:@hostname:1521:XE
karaf.lock.jdbc.driver=oracle.jdbc.OracleDriver
karaf.lock.jdbc.user=user
karaf.lock.jdbc.password=password
karaf.lock.jdbc.table=KARAF_LOCK
karaf.lock.jdbc.clustername=karaf
karaf.lock.jdbc.timeout=30
注意

karaf.lock.jdbc.url 需要活跃的 Oracle 系统 ID(SID)。这意味着,您必须在使用此特定锁定前手动创建数据库实例。

在 Derby 中配置 JDBC 锁定

如果您在 JDBC 锁定方案中使用 Derby 作为数据库,则 etc/system.properties 文件中的 karaf.lock.class 属性应指向 org.apache.karaf.main.lock.Derby 4.4.2Lock。例如,您可以配置 system.properties 文件,如下所示:

例 14.4. Derby 的 JDBC Lock 文件配置

karaf.lock=true
karaf.lock.class=org.apache.karaf.main.lock.DerbyJDBCLock
karaf.lock.jdbc.url=jdbc:derby://127.0.0.1:1527/dbname
karaf.lock.jdbc.driver=org.apache.derby.jdbc.ClientDriver
karaf.lock.jdbc.user=user
karaf.lock.jdbc.password=password
karaf.lock.jdbc.table=KARAF_LOCK
karaf.lock.jdbc.clustername=karaf
karaf.lock.jdbc.timeout=30

在 MySQL 中配置 JDBC 锁定

如果您在 JDBC 锁定方案中使用 MySQL 作为数据库,则 etc/system.properties 文件中的 karaf.lock.class 属性必须指向 org.apache.karaf.main.lock.main.MySQL JDBCLock。例如,您可以配置 system.properties 文件,如下所示:

例 14.5. MySQL 的 JDBC 锁定文件配置

karaf.lock=true
karaf.lock.class=org.apache.karaf.main.lock.MySQLJDBCLock
karaf.lock.jdbc.url=jdbc:mysql://127.0.0.1:3306/dbname
karaf.lock.jdbc.driver=com.mysql.jdbc.Driver
karaf.lock.jdbc.user=user
karaf.lock.jdbc.password=password
karaf.lock.jdbc.table=KARAF_LOCK
karaf.lock.jdbc.clustername=karaf
karaf.lock.jdbc.timeout=30

在 PostgreSQL 上配置 JDBC 锁定

如果您在 JDBC 锁定方案中使用 PostgreSQL 作为数据库,则 etc/system.properties 文件中的 karaf.lock.class 属性必须指向 org.apache.karaf.main.lock.main.PostgreSQL JDBCLock。例如,您可以配置 system.properties 文件,如下所示:

例 14.6. PostgreSQL 的 JDBC 锁定文件配置

karaf.lock=true
karaf.lock.class=org.apache.karaf.main.lock.PostgreSQLJDBCLock
karaf.lock.jdbc.url=jdbc:postgresql://127.0.0.1:5432/dbname
karaf.lock.jdbc.driver=org.postgresql.Driver
karaf.lock.jdbc.user=user
karaf.lock.jdbc.password=password
karaf.lock.jdbc.table=KARAF_LOCK
karaf.lock.jdbc.clustername=karaf
karaf.lock.jdbc.timeout=0

JDBC 锁定类

以下 JDBC 锁定类目前由 Apache Karaf 提供:

org.apache.karaf.main.lock.DefaultJDBCLock
org.apache.karaf.main.lock.DerbyJDBCLock
org.apache.karaf.main.lock.MySQLJDBCLock
org.apache.karaf.main.lock.OracleJDBCLock
org.apache.karaf.main.lock.PostgreSQLJDBCLock

14.3. 容器级别的锁定

概述

容器级别的锁定允许将捆绑包加载到二级内核实例中,以便提供更快的故障转移性能。在简单的文件和 JDBC 锁定机制中都支持容器级别的锁定。

配置容器级别锁定

要实现容器级别的锁定,请在 primary/secondary 设置的每个系统上的 etc/system.properties 文件中添加以下内容:

例 14.7. 容器级别的锁定配置

karaf.lock=true
karaf.lock.level=50
karaf.lock.delay=10000

karaf.lock.level 属性告知红帽 Fuse 实例启动启动 OSGi 容器的启动进程。然后,分配了相同启动级别或较低版本的捆绑包也会在该 Fuse 实例中启动。

捆绑包启动级别在 etc/startup.properties 中指定,格式为 BundleName.jar=level。核心系统捆绑包级别低于 50,因为用户捆绑包级别大于 50。

表 14.1. 捆绑包启动级别

开始级别行为

1

'cold' standby 实例。核心捆绑包未加载到容器中。辅助实例将等到锁定为启动服务器为止。

<50

一个"热"备用实例。核心捆绑包加载到容器中。二级实例将等到锁定后才启动用户级捆绑包。此级别的每个次要实例都可以访问控制台。

>50

不建议使用此设置,因为用户捆绑包将启动。

避免端口冲突

当在同一主机上使用"热"备用时,您需要将 JMX 远程端口设置为唯一值,以避免绑定冲突。您可以编辑 fuse 启动脚本(或子实例上的 karaf 脚本)使其包含以下内容:

DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote.port=1100 -Dcom.sun.management.jmxremote.authenticate=false"

第 15 章 URL 处理程序

Red Hat Fuse 中有很多上下文,您需要提供 URL 来指定资源的位置(例如,作为控制台命令的参数)。通常,在指定 URL 时,您可以使用 Fuse 的内置 URL 处理程序支持的任何方案。本附录介绍了所有可用的 URL 处理程序的语法。

15.1. 文件 URL 处理程序

15.1.1. 语法

文件 URL 的语法是 file:PathName,其中 PathName 是 Classpath 上提供的文件的相对或绝对路径名称。提供的 PathName 由 Java 的内置文件 URL 处理程序 解析。因此,PathName 语法在 Windows 上受到 Java 路径名称的一般约定:特别是 Windows,每个反斜杠都必须被另一个反斜杠转义,或者替换为正斜杠。

15.1.2. 例子

例如,考虑 Windows 上的路径名称,C:\Projects\camel-bundle\foo-1.0-SNAPSHOT.jar。以下示例显示了 Windows 中文件 URL 的正确 备选方案:

file:C:/Projects/camel-bundle/target/foo-1.0-SNAPSHOT.jar
file:C:\\Projects\\camel-bundle\\target\\foo-1.0-SNAPSHOT.jar

以下示例显示了 Windows 中文件 URL 的一些 不正确 的替代方法:

file:C:\Projects\camel-bundle\target\foo-1.0-SNAPSHOT.jar        // WRONG!
file://C:/Projects/camel-bundle/target/foo-1.0-SNAPSHOT.jar      // WRONG!
file://C:\\Projects\\camel-bundle\\target\\foo-1.0-SNAPSHOT.jar  // WRONG!

15.2. HTTP URL 处理程序

15.2.1. 语法

HTTP URL 具有标准语法 http:Host[:Port]/[Path][#AnchorName][?Query].您还可以使用 https 方案指定安全 HTTP URL。提供的 HTTP URL 由 Java 的内置 HTTP URL 处理程序解析,因此 HTTP URL 的行为方式类似于 Java 应用。

15.3. mvn URL Handler

15.3.1. 概述

如果您使用 Maven 构建捆绑包,或者知道特定捆绑包可从 Maven 存储库中获取,您可以使用 Mvn handler 方案来定位捆绑包。

注意

为确保 Mvn URL 处理程序可以找到本地和远程 Maven 工件,您可能会发现需要它来自定义 Mvn URL 处理程序配置。详情请查看 第 15.3.5 节 “配置 Mvn URL 处理程序”

15.3.2. 语法

Mvn URL 具有以下语法:

mvn:[repositoryUrl!]groupId/artifactId[/[version][/[packaging][/[classifier]]]]

其中 repositoryUrl optionally 指定 Maven 存储库的 URL。groupIdartifactId版本打包和 分类器 是标准的 Maven 协调,用于查找 Maven 工件。

15.3.3. 省略协调

当指定 Mvn URL 时,只需要 groupIdartifactId 协调。以下示例使用 groupIdorg.fusesource.example 以及 artifactId,bundle-demo 来引用 Maven 捆绑包:

mvn:org.fusesource.example/bundle-demo
mvn:org.fusesource.example/bundle-demo/1.1

当省略 版本 时,如第一个示例所示,它默认为 LATEST,它会根据可用的 Maven 元数据解析为最新版本。

要指定 分类器 值而不指定 打包版本 值,可以在 Mvn URL 中造成差距。同样,如果您想要指定没有 版本 值的 打包 值。例如:

mvn:groupId/artifactId///classifier
mvn:groupId/artifactId/version//classifier
mvn:groupId/artifactId//packaging/classifier
mvn:groupId/artifactId//packaging

15.3.4. 指定版本范围

当在 Mvn URL 中指定 version 值时,您可以指定一个版本范围(使用标准 Maven 版本范围语法)以代替简单的版本号。您可以使用方括号[]- 表示带括号和括号- 以表示独占范围。例如,范围 [1.0.4,2.0) 匹配任何版本 v,它们满足 1.0.4 busybox v < 2.0。您可以在 Mvn URL 中使用这个版本范围,如下所示:

mvn:org.fusesource.example/bundle-demo/[1.0.4,2.0)

15.3.5. 配置 Mvn URL 处理程序

首次使用 Mvn URL 前,您可能需要自定义 Mvn URL 处理程序设置,如下所示:

15.3.6. 检查 Mvn URL 设置

Mvn URL 处理程序解析对本地 Maven 存储库的引用,并维护远程 Maven 存储库列表。解决 Mvn URL 时,处理程序首先搜索本地存储库,然后搜索远程存储库以查找指定的 Maven artifiact。如果解析 Mvn URL 出现问题,您应该首先检查处理程序设置,以查看使用哪个本地存储库和远程存储库来解析 URL。

要检查 Mvn URL 设置,在控制台中输入以下命令:

JBossFuse:karaf@root> config:edit org.ops4j.pax.url.mvn
JBossFuse:karaf@root> config:proplist

config:edit 命令将配置实用程序的焦点切换到属于 org.ops4j.pax.url.mvn persistent ID 的属性。config:proplist 命令输出当前持久 ID 的所有属性设置。当专注于 org.ops4j.pax.url.mvn 时,您应该会看到类似如下的列表:

   org.ops4j.pax.url.mvn.defaultRepositories = file:/path/to/JBossFuse/jboss-fuse-7.11.1.fuse-7_11_1-00013-redhat-00003/system@snapshots@id=karaf.system,file:/home/userid/.m2/repository@snapshots@id=local,file:/path/to/JBossFuse/jboss-fuse-7.11.1.fuse-7_11_1-00013-redhat-00003/local-repo@snapshots@id=karaf.local-repo,file:/path/to/JBossFuse/jboss-fuse-7.11.1.fuse-7_11_1-00013-redhat-00003/system@snapshots@id=child.karaf.system
   org.ops4j.pax.url.mvn.globalChecksumPolicy = warn
   org.ops4j.pax.url.mvn.globalUpdatePolicy = daily
   org.ops4j.pax.url.mvn.localRepository = /path/to/JBossFuse/jboss-fuse-7.11.1.fuse-7_11_1-00013-redhat-00003/data/repository
   org.ops4j.pax.url.mvn.repositories = http://repo1.maven.org/maven2@id=maven.central.repo, https://maven.repository.redhat.com/ga@id=redhat.ga.repo, https://maven.repository.redhat.com/earlyaccess/all@id=redhat.ea.repo, https://repository.jboss.org/nexus/content/groups/ea@id=fuseearlyaccess
   org.ops4j.pax.url.mvn.settings = /path/to/jboss-fuse-7.11.1.fuse-7_11_1-00013-redhat-00003/etc/maven-settings.xml
   org.ops4j.pax.url.mvn.useFallbackRepositories = false
   service.pid = org.ops4j.pax.url.mvn

其中 localRepository 设置显示处理程序和 存储库 设置当前使用的本地存储库位置,则显示处理程序当前使用的远程存储库列表。

15.3.7. 编辑配置文件

要自定义 Mvn URL 处理程序的属性设置,请编辑以下配置文件:

InstallDir/etc/org.ops4j.pax.url.mvn.cfg

此文件中的设置允许您显式指定本地 Maven 存储库的位置,删除 Maven 存储库、Maven 代理服务器设置等。有关这些设置的详情,请查看 配置文件中的注释。

15.3.8. 自定义本地存储库的位置

特别是,如果您的本地 Maven 存储库位于非默认位置,您可能会发现需要对其进行显式配置,以便访问本地构建的 Maven 工件。在您的 org.ops4j.pax.url.mvn.cfg 配置文件中,取消注释 org.ops4j.pax.url.mvn.localRepository 属性,并将它设置为本地 Maven 存储库的位置。例如:

# Path to the local maven repository which is used to avoid downloading
# artifacts when they already exist locally.
# The value of this property will be extracted from the settings.xml file
# above, or defaulted to:
#     System.getProperty( "user.home" ) + "/.m2/repository"
#
org.ops4j.pax.url.mvn.localRepository=file:E:/Data/.m2/repository

15.3.9. 参考

有关 mvn URL 语法的详情,请查看原始 Pax URL Mvn Protocol 文档。

15.4. 嵌套 URL 处理程序

15.4.1. 概述

如果您需要引用未打包为捆绑包的 JAR 文件,您可以使用 Wrap URL 处理程序进行动态转换。Wrap URL 处理程序的实施基于 Peter Krien 的开源 Bnd 工具。

15.4.2. 语法

Wrap URL 具有以下语法:

wrap:locationURL[,instructionsURL][$instructions]

locationURL 可以是找到 JAR 的任何 URL(引用的 JAR 不会 作为捆绑包的格式)。可选的 instructionsURL 引用了一个 Bnd 属性文件,用于指定如何执行捆绑包转换。可选的 指令是 符号、和,由 Bnd 属性列表指定如何执行捆绑包转换。

15.4.3. 默认说明

在大多数情况下,默认的 Bnd 指令可用于嵌套 API JAR 文件。默认情况下,Wrap 将清单标头添加到 JAR 的 META-INF/Manifest.mf 文件中,如 表 15.1 “Wrapping a JAR 的默认说明” 所示。

表 15.1. Wrapping a JAR 的默认说明

manifest Header默认值

import-Package

*;resolution:=optional

export-Package

来自已封装 JAR 的所有软件包。

Bundle-SymbolicName

JAR 文件的名称,其中任何不在集合 [a-zA-Z0-9_-] 中的字符替换为下划线 _

15.4.4. 例子

以下 Wrap URL 找到 Maven 存储库中的 commons-logging JAR 版本 1.1,并使用默认的 Bnd 属性将其转换为 OSGi 捆绑包:

wrap:mvn:commons-logging/commons-logging/1.1

以下 Wrap URL 使用来自文件的 Bnd 属性,E:\Data\Examples\commons-logging-1.1.bnd:

wrap:mvn:commons-logging/commons-logging/1.1,file:E:/Data/Examples/commons-logging-1.1.bnd

以下 Wrap URL 指定 Bundle-SymbolicName 属性和 Bundle-Version 属性:

wrap:mvn:commons-logging/commons-logging/1.1$Bundle-SymbolicName=apache-comm-log&Bundle-Version=1.1

如果前面的 URL 用作命令行参数,可能需要转义美元符号 \$ 以防止命令行处理它,如下所示:

wrap:mvn:commons-logging/commons-logging/1.1\$Bundle-SymbolicName=apache-comm-log&Bundle-Version=1.1

15.4.5. 参考

有关嵌套 URL 处理程序 的详情,请查看以下引用:

15.5. war URL Handler

15.5.1. 概述

如果您需要在 OSGi 容器中部署 WAR 文件,您可以通过使用 war: 前缀为 WAR 文件自动添加必需的清单标头到 WAR 文件,如下所述。

15.5.2. 语法

使用以下语法之一指定 War URL:

war:warURL
warref:instructionsURL

第一个语法使用 war 方案指定 WAR 文件,该文件使用默认说明转换为捆绑包。warURL 可以是找到 WAR 文件的任何 URL。

第二个语法使用 warref 方案指定 Bnd 属性文件 instructionsURL,其中包含转换指令(包括特定于此处理程序的一些指令)。在这个语法中,引用的 WAR 文件的位置 没有明确 出现在 URL 中。WAR 文件通过属性文件中的 WAR 属性指定(必需) WAR-URL 属性。

15.5.3. WAR 特定属性/结构

.bnd 指令文件中的部分属性特定于 War URL 处理程序,如下所示:

WAR-URL
(必需)指定要转换为捆绑包的 War 文件的位置。
Web-ContextPath

指定在 Web 容器内部署此 Web 应用后用于访问此 Web 应用的 URL 路径。

注意

PAX Web 的早期版本使用 属性 Webapp-Context现在已弃用

15.5.4. 默认说明

默认情况下,War URL 处理程序将清单标头添加到 WAR 的 META-INF/Manifest.mf 文件中,如 表 15.2 “Wrapping a WAR 文件的默认指令” 所示。

表 15.2. Wrapping a WAR 文件的默认指令

manifest Header默认值

import-Package

javax.,org.xml.,org.w3c.*

export-Package

没有导出软件包。

Bundle-SymbolicName

WAR 文件的名称,其中任何不在集合 [a-zA-Z0-9_-\ . ] 的字符将被句点替换。

Web-ContextPath

没有默认值。但是,WAR 扩展器 默认使用 Bundle-SymbolicName 的值。

bundle-ClassPath

除了明确指定的任何类路径条目外,还会自动添加以下条目:

  • .
  • WEB-INF/classes
  • WEB-INF/lib 目录中的所有 JAR。

15.5.5. 例子

以下 War URL 在 Maven 存储库中找到 wicket-examples WAR 版本 1.4.7,并使用默认说明将其转换为 OSGi 捆绑包:

war:mvn:org.apache.wicket/wicket-examples/1.4.7/war

以下 Wrap URL 明确指定 Web-ContextPath

war:mvn:org.apache.wicket/wicket-examples/1.4.7/war?Web-ContextPath=wicket

以下 War URL 将 wicket -examples-1.4.7.bnd 文件中的 WAR 属性引用 WAR 文件,然后使用 .bnd 文件中的其他指令将 WAR 转换成 OSGi 捆绑包:

warref:file:E:/Data/Examples/wicket-examples-1.4.7.bnd

15.5.6. 参考

有关 war URL 语法的详情,请查看原始 Pax URL War Protocol 文档。

部分 II. 用户指南

这部分包含在红帽 Fuse 上 Apache Karaf 的配置和准备信息。

第 16 章 部署至 Apache Karaf 用户指南

摘要

在使用部署到 Apache 手册中的此用户指南部分前,您必须按照在 Apache Karaf 上安装 的说明安装最新版本的 Red Hat Fuse。

16.1. Fuse 配置简介

OSGi 配置管理服务指定部署服务的配置信息,并确保服务在激活时接收这些数据。

16.2. OSGi 配置

配置是名称值对列表,从 FUSE_HOME/etc 目录中的 .cfg 文件中读取。文件使用 Java 属性文件格式解释。文件名映射到要配置的服务的持久标识符(PID)。在 OSGi 中,PID 用于识别容器重启后的服务。

16.3. 配置文件

您可以使用以下文件配置 Red Hat Fuse 运行时:

表 16.1. Fuse 配置文件

filename描述

config.properties

容器的主配置文件。

custom.properties

容器自定义属性的主配置文件。

keys.properties

列出可以使用基于 SSH 密钥的身份验证访问 Fuse 运行时的用户。文件内容采用 username=publicKey,role

org.apache.karaf.features.repos.cfg

功能存储库 URL。

org.apache.karaf.features.cfg

配置要注册的功能存储库列表,以及首次启动时要安装的功能列表。

org.apache.karaf.jaas.cfg

配置 Karaf JAAS 登录模块的选项。主要用来配置加密密码(默认为禁用)。

org.apache.karaf.log.cfg

配置日志 控制台命令的输出。

org.apache.karaf.management.cfg

配置 JMX 系统。

org.apache.karaf.shell.cfg

配置远程控制台的属性。

org.ops4j.pax.logging.cfg

配置日志记录系统。

org.ops4j.pax.transx.tm.narayana.cfg

Narayana 事务管理器配置

org.ops4j.pax.url.mvn.cfg

配置其他 URL 解析器。

org.ops4j.pax.web.cfg

配置默认的 Undertow 容器(Web 服务器)。请参阅红帽 Fuse Apache CXF 安全指南中的 Undertow HTTP 服务器的安全。

startup.properties

指定在容器中启动哪些捆绑包及其启动级别。条目采用格式 bundle=低级

system.properties

指定 Java 系统属性。此文件中设置的任何属性可在运行时使用 System.getProperties()

users.properties

列出可以访问 Fuse 运行时的用户,也可通过 Web 控制台或 Web 控制台访问。文件内容采用 用户名=密码角色

setenvsetenv.bat

此文件位于 /bin 目录中。它用于设置 JVM 选项。文件内容的格式是 JAVA_MIN_MEM=512M,其中 512M 是 Java 内存大小。如需更多信息,请参阅 第 16.6 节 “设置 Java 选项”

16.4. 高级 Undertow 配置

16.4.1. IO 配置

自 PAXWEB-1255 起,可以更改监听器使用的 XNIO worker 和缓冲池的配置。在 undertow.xml 模板中有一个指定某些与 IO 相关参数的默认值的部分:

<!-- Only "default" worker and buffer-pool are supported and can be used to override the default values used by all listeners
    buffer-pool:
     - buffer-size defaults to:
        - when < 64MB of Xmx: 512
        - when < 128MB of Xmx: 1024
        - when >= 128MB of Xmx: 16K - 20
     - direct-buffers defaults to:
        - when < 64MB of Xmx: false
        - when >= 64MB of Xmx: true
    worker:
     - io-threads defaults to Math.max(Runtime.getRuntime().availableProcessors(), 2);
     - task-core-threads and task-max-threads default to io-threads * 8
-->

<!--
<subsystem xmlns="urn:jboss:domain:io:3.0">
    <buffer-pool name="default" buffer-size="16364" direct-buffers="true" />
    <worker name="default" io-threads="8" task-core-threads="64" task-max-threads="64" task-keepalive="60000" />
</subsystem>
-->

可以指定以下 buffer-pool 参数:

buffer-size
指定用于 IO 操作的缓冲区的大小。如果没有指定,大小会根据可用内存计算。
direct-buffers
确定应使用 java.nio.ByteBuffer#allocateDirect 或 java.nio.ByteBuffer#allocate。

可指定以下 worker 参数:

io-threads
为 worker 创建的 I/O 线程数量。如果没有指定,线程数量将设置为 CPU 的数量 2。
task-core-threads
核心任务线程池的线程数量。
task-max-threads
worker 任务线程池的最大线程数量。如果没有指定,则最大线程数被设置为 CPU 340 16 的数量。

16.4.2. worker IO 配置

可以在每个服务或捆绑包的基础上配置 Undertow 线程池及其名称,这有助于从 Hawtio 控制台进行监控并更有效地调试。

在捆绑包蓝图配置文件中(通常存储在 Maven 项目中的 src/main/resources/OSGI-INF/blueprint 目录下),您可以像以下示例所示配置 workerIOName 和 ThreadPool。

例 16.1. httpu:engine-factory 元素带有 workerIOName 和 ThreadPool 配置

<httpu:engine-factory>
    <httpu:engine port="9001">
        <httpu:threadingParameters minThreads="99" maxThreads="777" workerIOThreads="8" workerIOName="WorkerIOTest"/>
    </httpu:engine>
</httpu:engine-factory>

可指定 以下线程参数

minThreads
指定 worker 任务线程池的"core"线程数量。通常,每个 CPU 内核至少应有 10 个。
最大线程数
指定 worker 任务线程池的最大线程数量。

可指定以下 worker 参数:

workerIOThreads
指定为 worker 创建的 I/O 线程数量。若不指定,则会选择一个默认。每个 CPU 内核一个 IO 线程是合理的默认值。
workerIOName
指定 worker 的名称。如果没有指定,将选择默认的 "XNIO-1"。

16.5. 配置文件命名规则

配置文件的文件命名规则取决于配置是否适用于 OSGi 托管服务还是 OSGi 托管服务的工厂。

OSGi 托管服务的配置文件遵循以下命名约定:

<PID>.cfg

其中,& lt;PID > 是 OSGi 管理服务 的持久 ID (如 OSGi 配置管理员规范中所定义)。永久 ID 通常是以点分隔的,例如 org.ops4j.pax.web

OSGi 管理的服务 Factory 的配置文件遵循以下命名约定:

<PID>-<InstanceID>.cfg

其中 <PID > 是 OSGi Managed Service Factory 的 持久 ID。如果是托管服务的 < PID>, 您可以附加一个连字符加一个任意实例 ID < InstanceID>。然后,受管服务工厂会为它找到的每个 < InstanceID> 创建一个唯一服务实例。

16.6. 设置 Java 选项

可以使用 Linux 中的 /bin/setenv 文件或 Windows 的 bin/setenv.bat 文件来设置 Java 选项。使用此文件直接设置一组 Java 选项: JAVA_MIN_MEM、JAVA_MAX_MEM、JAVA_PERM_MEM、JAVA_MAX_PERM_MEM。可使用 EXTRA_JAVA_OPTS 变量设置其他 Java 选项。

例如,要为 JVM 使用分配最小内存

JAVA_MIN_MEM=512M # Minimum memory for the JVM
To set a Java option other than the direct options, use
EXTRA_JAVA_OPTS="Java option"
For example,
EXTRA_JAVA_OPTS="-XX:+UseG1GC"

16.7. 配置控制台命令

有多个控制台命令可用于更改或交集 Fuse 7.11 的配置。

如需有关 config: 命令的更多详情,请参阅 Apache Karaf Console Reference 中的 Config 部分。

16.8. JMX ConfigMBean

在 JMX 层,M Bean 专用于配置管理。

ConfigMBean 对象名称是: org.apache.karaf:type=config,name=*'

14.1.2.1.属性

config MBean 包含所有配置 PID 的列表。

14.1.2.2.操作

表 16.2. JMX MBean 操作

操作名称描述

listProperties(pid)

为配置 pid 返回属性列表(property=value 格式)。

删除Property(pid, property)

从配置 pid 中删除 属性。

appendProperty(pid, property, value)

在配置 pid 的属性值末尾附加值。

setProperty(pid, property, value)

为配置 pid 的值设置值。

delete(pid)

删除 pid 识别的配置。

create(pid)

使用 pid 创建一个空(没有任何属性)配置。

更新(pid、属性)

更新使用 pid 标识的配置,并使用提供的属性映射。

16.9. 使用控制台

16.9.1. 可用命令

要在控制台中查看可用命令列表,您可以使用 帮助

karaf@root()> help
bundle                            Enter the subshell
bundle:capabilities               Displays OSGi capabilities of a given bundles.
bundle:classes                    Displays a list of classes/resources contained in the bundle
bundle:diag                       Displays diagnostic information why a bundle is not Active
bundle:dynamic-import             Enables/disables dynamic-import for a given bundle.
bundle:find-class                 Locates a specified class in any deployed bundle
bundle:headers                    Displays OSGi headers of a given bundles.
bundle:id                         Gets the bundle ID.
...

您有简短描述的所有命令列表。

您可以使用 tab 键获得所有命令的快速列表:

karaf@root()> Display all 294 possibilities? (y or n)
...

16.9.2. 子 shell 和完成模式

命令具有作用域和名称。例如,命令 feature:list 包含 功能 作为范围,列表 为 name。

OSSM"groups"按范围表示命令。每个范围都组成一个子 shell。

您可以使用其完全限定名称(scope:name)直接执行命令:

karaf@root()> feature:list
...

或在子 shell 中输入命令并键入命令上下文到子 shell:

karaf@root()> feature
karaf@root(feature)> list

您可以通过键入 subshell 名称(以下特性)直接在子 shell 中输入。您可以从子 shell 直接"切换"到另一个:

karaf@root()> feature
karaf@root(feature)> bundle
karaf@root(bundle)>

提示符可显示介于()之间的当前子 shell。

exit 命令进入父子 shell:

karaf@root()> feature
karaf@root(feature)> exit
karaf@root()>

completion 模式定义了 tab 键和 help 命令的行为。

您有三种不同的模式可用:

  • GLOBAL
  • FIRST
  • 子 SHELL

您可以使用 etc/org.apache.karaf.shell.cfg 文件中的 completionMode 属性来定义默认的完成模式。默认情况下,您有:

completionMode = GLOBAL

您还可以使用 shell:completion 命令更改完成模式"在 fly"中(同时使用 Karaf shell 控制台):

karaf@root()> shell:completion
GLOBAL
karaf@root()> shell:completion FIRST
karaf@root()> shell:completion
FIRST

shell:完成 可告知您使用的当前完成模式。您还可以提供您想要的新完成模式。

GLOBAL completion 模式是 CIB 4.0.0 中的默认模式(主要用于转换)。

GLOBAL 模式并不实际使用 subshell:它的行为与之前的 Karaf 版本相同。

当您键入 tab 键时,您所处的子 shell 是什么,补全将显示所有命令和所有别名:

karaf@root()> <TAB>
karaf@root()> Display all 273 possibilities? (y or n)
...
karaf@root()> feature
karaf@root(feature)> <TAB>
karaf@root(feature)> Display all 273 possibilities? (y or n)

FIRST completion 模式是 GLOBAL completion 模式的替代模式。

如果在根级别子 shell 中键入 tab 键,补全将显示命令以及所有子 shell 的别名(如 GLOBAL 模式)。但是,如果您在子 shell 中键入 tab 键,补全将仅显示当前子 shell 的命令:

karaf@root()> shell:completion FIRST
karaf@root()> <TAB>
karaf@root()> Display all 273 possibilities? (y or n)
...
karaf@root()> feature
karaf@root(feature)> <TAB>
karaf@root(feature)>
info install list repo-add repo-list repo-remove uninstall version-list
karaf@root(feature)> exit
karaf@root()> log
karaf@root(log)> <TAB>
karaf@root(log)>
clear display exception-display get log set tail

SUBSHELL 补全模式是真正的子 shell 模式。

如果在 root 级别上键入 tab 键,则 补全会显示子 shell 命令(转至子 shell)以及全局别名。您处于子 shell 中后,如果您键入 TAB 键,则完成将显示当前子 shell 的命令:

karaf@root()> shell:completion SUBSHELL
karaf@root()> <TAB>
karaf@root()>
* bundle cl config dev feature help instance jaas kar la ld lde log log:list man package region service shell ssh system
karaf@root()> bundle
karaf@root(bundle)> <TAB>
karaf@root(bundle)>
capabilities classes diag dynamic-import find-class headers info install list refresh requirements resolve restart services start start-level stop
uninstall update watch
karaf@root(bundle)> exit
karaf@root()> camel
karaf@root(camel)> <TAB>
karaf@root(camel)>
backlog-tracer-dump backlog-tracer-info backlog-tracer-start backlog-tracer-stop context-info context-list context-start context-stop endpoint-list route-info route-list route-profile route-reset-stats
route-resume route-show route-start route-stop route-suspend

16.9.3. 像环境一样的 UNIX

Karaf 控制台提供完整的 Unix 控制台,如环境。

16.9.3.1. help 或 man

我们已看到 help 命令的用法来显示所有可用的命令。

但是,您还可以使用 help 命令获取有关命令或 man 命令的详细信息,它是 help 命令的别名。您还可以通过将 --help 选项用于 命令,使用另外一种形式来获取命令的帮助。

因此这些命令

karaf@root()> help feature:list
karaf@root()> man feature:list
karaf@root()> feature:list --help

所有都生成相同的帮助输出:

DESCRIPTION
        feature:list

        Lists all existing features available from the defined repositories.

SYNTAX
        feature:list [options]

OPTIONS
        --help
                Display this help message
        -o, --ordered
                Display a list using alphabetical order
        -i, --installed
                Display a list of all installed features only
        --no-format
                Disable table rendered output

16.9.3.2. completion

当您键入 tab 键时,Batton 会尝试完成:

  • subshell
  • commands
  • 别名
  • 命令参数
  • 命令选项

16.9.3.3. Alias

别名是与给定命令关联的另一个名称。

shell:alias 命令创建新别名。例如,为实际 feature:list -i 命令创建 list-installed-features 别名,您可以执行以下操作:

karaf@root()> alias "list-features-installed = { feature:list -i }"
karaf@root()> list-features-installed
Name       | Version | Required | State   | Repository     | Description
------------------------------------------------------------------------------------------------------------------------------
feature    | 4.0.0   | x        | Started | standard-4.0.0 | Features Support
shell      | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Shell
deployer   | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Deployer
bundle     | 4.0.0   | x        | Started | standard-4.0.0 | Provide Bundle support
config     | 4.0.0   | x        | Started | standard-4.0.0 | Provide OSGi ConfigAdmin support
diagnostic | 4.0.0   | x        | Started | standard-4.0.0 | Provide Diagnostic support
instance   | 4.0.0   | x        | Started | standard-4.0.0 | Provide Instance support
jaas       | 4.0.0   | x        | Started | standard-4.0.0 | Provide JAAS support
log        | 4.0.0   | x        | Started | standard-4.0.0 | Provide Log support
package    | 4.0.0   | x        | Started | standard-4.0.0 | Package commands and mbeans
service    | 4.0.0   | x        | Started | standard-4.0.0 | Provide Service support
system     | 4.0.0   | x        | Started | standard-4.0.0 | Provide System support
kar        | 4.0.0   | x        | Started | standard-4.0.0 | Provide KAR (KARaf archive) support
ssh        | 4.0.0   | x        | Started | standard-4.0.0 | Provide a SSHd server on Karaf
management | 4.0.0   | x        | Started | standard-4.0.0 | Provide a JMX MBeanServer and a set of MBeans in

登录时,Apache Karaf 控制台会读取 etc/shell.init.script 文件,您可以在其中创建别名。它类似于 Unix 上的 bashrc 或配置文件文件。

ld = { log:display $args } ;
lde = { log:exception-display $args } ;
la = { bundle:list -t 0 $args } ;
ls = { service:list $args } ;
cl = { config:list "(service.pid=$args)" } ;
halt = { system:shutdown -h -f $args } ;
help = { *:help $args | more } ;
man = { help $args } ;
log:list = { log:get ALL } ;

您可以在此处看到默认可用的别名:

  • ld 是一个显示日志的简短形式(别名至 log:display 命令)
  • lde 是一个显示异常的简短形式(原因为 log:exception-display 命令)
  • la 是一个列出所有捆绑包(别名至 bundle:list -t 0 命令)的简短形式。
  • ls 是一个简短形式,用于列出所有服务(别名至 service:list 命令)
  • CL 是一个简短形式,用于列出所有配置(别名至 config:list 命令)
  • halt 是一个关闭 Apache Karaf(别名至 system:shutdown -h -f 命令的简短形式)
  • help 是一个显示帮助的简短形式(别名为 *:help 命令)
  • man 与帮助相同( 帮助 命令别名)
  • log:list 显示所有日志记录器和级别(别名至 log:get ALL 命令)

您可以在 etc/shell.init.script 文件中创建自己的别名。

16.9.3.4. 密钥绑定

与在大多数 Unix 环境中一样,Patton 控制台支持一些键绑定:

  • 要在命令历史记录中导航的箭头键
  • CTRL-D 注销/shutdown Karaf
  • 使用 CTRL-R 搜索之前执行的命令
  • 使用 CTRL-U 删除行

16.9.3.5. pipe

您可以将一个命令的输出作为输入传送到另一个命令的输出。这是一个管道,使用 | 字符:

karaf@root()> feature:list |grep -i war
pax-war                       | 4.1.4                            |          | Uninstalled | org.ops4j.pax.web-4.1.4  | Provide support of a full WebContainer
pax-war-tomcat                | 4.1.4                            |          | Uninstalled | org.ops4j.pax.web-4.1.4  |
war                           | 4.0.0                            |          | Uninstalled | standard-4.0.0           | Turn Karaf as a full WebContainer
blueprint-web                 | 4.0.0                            |          | Uninstalled | standard-4.0.0           | Provides an OSGI-aware Servlet ContextListener fo

16.9.3.6. grep, more, find, …​

Karaf 控制台提供一些与 Unix 环境类似的核心命令:

  • shell:alias 为现有命令创建别名
  • shell:cat 显示文件或 URL 的内容
  • shell:clear 清除当前控制台显示
  • shell:completion 显示或更改当前完成模式
  • shell:date 显示当前日期(可选使用格式)
  • shell:每个 参数列表都执行冲突
  • shell:echo echoes 并打印到 stdout 的参数
  • shell:编辑 当前文件或 URL 的文本编辑器
  • shell:env 显示或设置 shell 会话变量的值
  • shell:exec 执行系统命令
  • shell:grep 打印与给定模式匹配的行
  • shell:head 显示输入的第一行
  • shell:history 打印命令历史记录
  • shell:如果 允许您使用条件(如果是,则)在脚本中使用其他块
  • shell:info 会输出有关当前 Karaf 实例的各种信息
  • shell:java 执行 Java 应用程序
  • shell: 无 文件页器
  • shell:logout 断开 shell 与当前会话的连接
  • shell: more is a file pager
  • shell:创建新 Java 对象
  • shell:printf 格式和打印参数
  • shell: sleep sleep for a bit to up
  • shell:排序 写入所有文件到 stdout 的串联
  • shell:源 执行脚本中包含的命令
  • 当执行命令抛出异常时,shell:stack-traces-print 会在控制台中打印完整的堆栈追踪
  • shell:tac 捕获 STDIN,并将其返回为字符串
  • shell:tail 显示输入的最后一行
  • shell:threads 打印当前线程
  • shell:watch 定期执行命令并刷新输出
  • shell:wc 会为每个文件打印换行符、字和字节数
  • shell: when 循环条件为 true

您不必使用 命令的完全限定名称,只要其唯一,就可以直接使用命令名称。因此,您可以使用 'head' 而不是 'shell:head'

同样,您可以使用 help 命令或 --help 选项查找这些命令的详细信息以及这些命令的所有选项。

16.9.3.7. 脚本

Apache Karaf 控制台支持完整的脚本语言,类似于 Unix 上的 bash 或 csh。

每个 (shell:each)命令可以迭代列表:

karaf@root()> list = [1 2 3]; each ($list) { echo $it }
1
2
3
注意

可使用 shell:while 命令编写同一循环:

karaf@root()> a = 0 ; while { %((a+=1) <= 3) } { echo $a }
1
2
3

您可以自行创建列表(如上例中的 ),或者某些命令也可以返回列表。

我们可以注意到,控制台使用名称列表创建了一个"session"变量,您可以使用 $ list 进行访问。

$it 变量是一个与当前对象对应的隐式变量(其中当前迭代的值)。

使用 [] 创建列表时,Apache Karaf 控制台会创建一个 Java ArrayList。这意味着,您可以使用 ArrayList 对象中的方法(如 instance get 或 size):

karaf@root()> list = ["Hello" world]; echo ($list get 0) ($list get 1)
Hello world

在这里,我们可以注意,在对象上调用方法直接使用 (对象方法参数)。此处 ($list get 0) 表示 $list.get(0),其中 $list 是 ArrayList。

class 表示法将显示有关对象的详细信息:

karaf@root()> $list class
...
ProtectionDomain     ProtectionDomain  null
 null
 <no principals>
 java.security.Permissions@6521c24e (
 ("java.security.AllPermission" "<all permissions>" "<all actions>")
)


Signers              null
SimpleName           ArrayList
TypeParameters       [E]

您可以将变量"广播"到指定类型。

karaf@root()> ("hello world" toCharArray)
[h, e, l, l, o,  , w, o, r, l, d]

如果失败,您会看到广播异常:

karaf@root()> ("hello world" toCharArray)[0]
Error executing command: [C cannot be cast to [Ljava.lang.Object;

您可以使用 shell:source 命令"call"一个脚本:

karaf@root> shell:source script.txt
True!

where script.txt contains:

foo = "foo"
if { $foo equals "foo" } {
  echo "True!"
}
注意

编写脚本时空格很重要。例如,以下脚本不正确:

if{ $foo equals "foo" } ...

并使用以下内容失败:

karaf@root> shell:source script.txt
Error executing command: Cannot coerce echo "true!"() to any of []

因为 if 语句后缺少了空格。

对于别名,您可以在 etc/shell.init.script 文件中创建初始化脚本。您还可以使用别名命名脚本。实际上,别名只是脚本。

详情请参阅开发人员指南中的脚本部分。

16.9.4. 安全性

Apache Karaf 控制台支持基于角色的访问控制(RBAC)安全机制。这意味着,根据连接到控制台的用户,您可以根据用户的组和角色定义、执行某些命令的权限,或者限制参数允许的值。

控制台 安全性在本指南的安全部分 进行了详细。

16.10. 置备

Apache Karaf 支持使用 Karaf 功能的概念来置备应用程序和模块。

16.10.1. Application(应用程序)

通过置备应用程序,这意味着安装所有模块、配置和传输应用程序。

16.10.2. OSGi

它原生支持 OSGi 应用程序的部署。

OSGi 应用程序是一组 OSGi 捆绑包。OSGi 捆绑包是一个常规 jar 文件,它带有 jar MANIFEST 中的其他元数据。

在 OSGi 中,捆绑包可以依赖其他捆绑包。因此,这意味着大多数时候部署 OSGi 应用程序,您首先需要部署应用程序所需的许多其他捆绑包。

因此,您必须首先找到这些捆绑包,安装捆绑包。同样,这些"依赖项"捆绑包可能需要其他捆绑包来满足自己的依赖项。

通常,应用程序需要配置(请参阅用户指南中的 [Configuration 部分| 配置])。因此,在除了依赖捆绑包外,还需要创建或部署配置,然后才能启动您的应用程序。

正如我们看到的那样,应用程序的配置可能非常长且非常快。

16.10.3. 功能和解析程序

Apache Karaf 提供简单而灵活的方式来置备应用程序。

在 Apache Karaf 中,应用程序调配是一个 Apache Karaf "feature"。

功能描述了应用程序:

  • 一个名称
  • 一个版本
  • 可选描述(以长描述为事件)
  • 组捆绑包
  • (可选)设置配置或配置文件
  • (可选)依赖项功能集

安装功能时,Apache Karaf 安装功能中描述的所有资源。这意味着它将自动解析并安装功能中描述的所有捆绑包、配置和依赖项功能。

功能解析器检查服务要求,并安装提供与要求匹配的服务的捆绑包。默认模式只为"new 风格"功能存储库启用此行为(基本来说,模式的功能库 XML 等于 1.3.0)。它不适用于"旧风格"功能存储库(与 Karaf 2 或 3 起)。

您可以使用 serviceRequirements 属性在 etc/org.apache.karaf.features.cfg 文件中更改服务要求强制实施模式。

serviceRequirements=default

可能的值有:

  • Disable: 服务要求完全忽略,对于"旧风格"和"新风格"功能存储库,都会完全忽略
  • 默认值:对于"旧风格"功能存储库,会忽略服务要求,并为"新风格"功能存储库启用。
  • enforce:服务要求总是被验证,用于"旧风格"和"新风格的功能存储库。

另外,一个功能也可以定义要求。在这种情况下,Bill 可以自动进行额外的捆绑包或功能,从而满足要求。

功能具有完整的生命周期:安装、启动、停止、更新、卸载。

16.10.4. 功能软件仓库

功能在 XML 描述符中描述。这个 XML 文件包含一组功能的描述。

XML 描述符的名称为"功能存储库"。在安装功能前,您必须注册提供该功能的功能存储库(使用 feature:repo-add 命令或 FeatureMBean 所述)。

例如,以下 XML 文件(或"功能存储库")描述了 feature1feature2 功能:

<features xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
  <feature name="feature1" version="1.0.0">
    <bundle>...</bundle>
    <bundle>...</bundle>
  </feature>
  <feature name="feature2" version="1.1.0">
    <feature>feature1</feature>
    <bundle>...</bundle>
  </feature>
</features>

我们可能会注意到 XML 的功能带有 schema。查看详情的用户指南的 [Features XML Schema 部分|provisioning-schema]。feature1 功能在版本 1.0.0 中提供,它包含两个捆绑包。& lt;bundle /> 元素包含捆绑包工件的 URL(详情请参阅 [Artifacts repositories 和 URL 部分|urls])。如果您安装 feature1 功能(使用 feature:install 或 FeatureMBean),Apache Karaf 将自动安装两个捆绑包。feature2 功能在 1.1.0 版本中可用,包含对 feature1 功能和捆绑包的引用。& lt;feature/& gt; 元素包含功能的名称。可以使用 version 属性定义为 <feature/&gt ; 元素(&lt ;feature version="1.0.0">feature1</feature>)的特定功能版本。如果未指定 version 属性,Apache Karaf 将安装最新的可用版本。如果您安装 feature2 功能(使用 feature:install 或 FeatureMBean),Apache Karaf 将自动安装 feature1 (如果还没有安装)和捆绑包。

使用功能 XML 文件的 URL 注册功能存储库。

功能状态存储在 Apache Karaf 缓存中(在 KARAF_DATA 文件夹中)。您可以重启 Apache Karaf,之前安装的功能会在重启后保留安装且可用。如果您进行一个干净的重启,或者删除 Apache Karaf 缓存(删除 KARAF_DATA 文件夹),则之前安装的所有功能存储库都将丢失:您必须再次注册功能并再次安装功能。要防止这种行为,您可以将功能指定为引导功能。

16.10.5. 引导特性

您可以将一些功能描述为引导功能。即使之前还没有通过 feature:install 或 FeatureMBean 自动安装,它会被 Apache Karaf 自动安装。

Apache Karaf 功能配置位于 etc/org.apache.karaf.features.cfg 配置文件中。

这个配置文件包含两个属性来定义引导功能:

  • featuresRepositories 包含功能存储库(功能 XML) URL 的列表(以概述形式)。
  • featuresBoot 包含要在启动时安装的功能的列表(以空格分隔)。

16.10.6. 升级功能

您可以通过安装相同的功能(使用相同的 SNAPSHOT 或不同的版本)来更新发行版本。

由于功能生命周期,您可以控制功能的状态(启动、停止等)。

您还可以使用模拟来查看更新将做什么。

16.10.7. overrides

功能中定义的捆绑包可以使用文件 etc/overrides.properties 覆盖。文件的每一行都定义一个覆盖。语法为: <bundle-uri>[;range="[min,max)"]。如果覆盖版本大于覆盖捆绑包的版本和范围匹配,给定捆绑包中的功能定义中会覆盖的所有捆绑包和范围匹配。如果没有提供范围,则假设在微版本级别的兼容性。

例如,覆盖 mvn:org.ops4j.pax.logging/pax-logging-service/1.8.5 将 overide pax-logging-service 1.8.3 而不是 1.8.6 或 1.7.0。

16.10.8. 功能捆绑包

16.10.8.1. 开始级别

默认情况下,功能部署的捆绑包在 karaf.startlevel.bundle 属性中,对 etc/config.properties 配置文件中的 etc/config.properties 配置文件中的值具有开始级别。

此值可由功能 XML 中的 < bundle /> 元素的 开始级别 属性 "overrided"。

  <feature name="my-project" version="1.0.0">
    <bundle start-level="80">mvn:com.mycompany.myproject/myproject-dao</bundle>
    <bundle start-level="85">mvn:com.mycompany.myproject/myproject-service</bundle>
  </feature>

start-level 属性可确保在使用它的捆绑包之前启动 myproject-dao 捆绑包。

通过定义您需要的软件包或服务,一种更好的解决方案就是让 OSGi 框架了解您的依赖情况。它比设置开始级别更强大。

16.10.8.2. 模拟、启动和停止

您可以使用 -t 选项对 feature:install 命令模拟功能安装。

您可以在不启动捆绑包的情况下安装捆绑包。默认情况下,功能中的捆绑包会自动启动。

功能可以指定不应自动启动捆绑包(捆绑包处于已解析状态)。要做到这一点,功能可在 < bundle /> 元素中指定 start 属性为 false:

  <feature name="my-project" version="1.0.0">
    <bundle start-level="80" start="false">mvn:com.mycompany.myproject/myproject-dao</bundle>
    <bundle start-level="85" start="false">mvn:com.mycompany.myproject/myproject-service</bundle>
  </feature>

16.10.8.3. 依赖项

一个捆绑包可以被标记为依赖项,使用 < bundle /> 元素上的 dependencies 属性设置为 true。

解析器可以使用此信息来计算要安装的捆绑包的完整列表。

16.10.9. 依赖功能

功能可以依赖于一组其他功能:

  <feature name="my-project" version="1.0.0">
    <feature>other</feature>
    <bundle start-level="80" start="false">mvn:com.mycompany.myproject/myproject-dao</bundle>
    <bundle start-level="85" start="false">mvn:com.mycompany.myproject/myproject-service</bundle>
  </feature>

将安装 my-project 功能后,还会自动安装 其他功能

可以为依赖功能定义版本范围:

<feature name="spring-dm">
  <feature version="[2.5.6,4)">spring</feature>
  ...
</feature>

将安装范围中最高版本的功能。

如果指定了单个版本,则该范围将被视为开放范围。

如果未指定,则安装最高可用。

要指定准确版本,请使用 [3.1,3.1] 等封闭范围。

16.10.9.1. 功能先决条件

先决条件功能是特殊的依赖项类型。如果将 先决条件 属性添加到依赖的功能标签中,它将强制安装,并在安装实际功能前在依赖的功能中激活捆绑包。如果给定功能中的捆绑包没有使用预安装的 URL,如嵌套或 war,这可能很方便。

16.10.10. 功能配置

功能 XML 中的 <config /> 元素允许创建和/或填充配置(由配置 PID 识别)的功能。

<config name="com.foo.bar">
  myProperty = myValue
</config>

< config/> 元素的 name 属性与配置 PID 对应(详情请参阅 [Configuration 部分|configuration])。

该功能的安装将与丢弃 etc 文件夹中的名为 com.foo.bar.cfg 的文件具有同样的影响。

< config/&gt; 元素的内容是一组属性,遵循 key=value 标准。

16.10.11. 功能配置文件

一个功能可以指定 & lt;config file/& gt; 元素,而不是使用 <config/> 元素。

<configfile finalname="/etc/myfile.cfg" override="false">URL</configfile>

< config/> 元素不直接操作 Apache Karaf 配置层(就像使用 &lt; config/&gt; 元素时),<configfile/> 元素会直接获取一个 URL 指定的文件,并复制由 finalname 属性指定的位置的文件。

如果没有指定,则位置相对于 KARAF_BASE 变量。也可以使用如 ${karaf.home}、${karaf.base}、${karaf.etc} 甚至系统属性等变量。

例如:

<configfile finalname="${karaf.etc}/myfile.cfg" override="false">URL</configfile>

如果文件已存在于所需的位置,并且跳过了配置文件的部署,因为已有的文件可能会包含自定义。这种行为可通过覆盖设置为 true 来覆盖

文件 URL 是 Apache Karaf 支持的任何 URL(有关详细信息,请参阅用户指南的 [Artifacts repositories 和 URL|urls])。

16.10.11.1. 要求

功能也可以指定预期的要求。功能解析器将尝试满足要求。为此,它会检查功能和捆绑包功能,并将自动安装捆绑包以满足要求。

例如,一个功能可以包含以下内容:

<requirement>osgi.ee;filter:=&quot;(&amp;(osgi.ee=JavaSE)(!(version&gt;=1.8)))&quot;</requirement>

要求指定只有在 JDK 版本不是 1.8(因此基本上为 1.7)时,该功能才会正常工作。

当一个可选的依赖项满足时,功能解析器也可以刷新捆绑包,从而重新运行可选的导入。

16.10.12. 命令

16.10.12.1. feature:repo-list

feature:repo-list 命令列出所有注册的功能存储库:

karaf@root()> feature:repo-list
Repository               | URL
--------------------------------------------------------------------------------------
org.ops4j.pax.cdi-0.12.0 | mvn:org.ops4j.pax.cdi/pax-cdi-features/0.12.0/xml/features
org.ops4j.pax.web-4.1.4  | mvn:org.ops4j.pax.web/pax-web-features/4.1.4/xml/features
standard-4.0.0           | mvn:org.apache.karaf.features/standard/4.0.0/xml/features
enterprise-4.0.0         | mvn:org.apache.karaf.features/enterprise/4.0.0/xml/features
spring-4.0.0             | mvn:org.apache.karaf.features/spring/4.0.0/xml/features

每个仓库都有一个名称和功能 XML 的 URL。

当您注册功能存储库 URL(使用 feature:repo-add 命令或 FeatureMBean)时,Apache Karaf 解析功能 XML。如果要强制 Apache Karaf 重新加载功能存储库 URL(因此更新功能定义),您可以使用 -r 选项:

karaf@root()> feature:repo-list -r
Reloading all repositories from their urls

Repository               | URL
--------------------------------------------------------------------------------------
org.ops4j.pax.cdi-0.12.0 | mvn:org.ops4j.pax.cdi/pax-cdi-features/0.12.0/xml/features
org.ops4j.pax.web-4.1.4  | mvn:org.ops4j.pax.web/pax-web-features/4.1.4/xml/features
standard-4.0.0           | mvn:org.apache.karaf.features/standard/4.0.0/xml/features
enterprise-4.0.0         | mvn:org.apache.karaf.features/enterprise/4.0.0/xml/features
spring-4.0.0             | mvn:org.apache.karaf.features/spring/4.0.0/xml/features

16.10.12.2. feature:repo-add

要注册功能存储库(以及 Apache Karaf 中提供新功能),您必须使用 feature:repo-add 命令。

feature:repo-add 命令需要 name/url 参数。这个参数接受:

  • 功能存储库 URL。它是一个直接指向功能 XML 文件的 URL。支持用户指南的 [Artifacts 软件仓库和 URL 部分|urls] 中描述的 URL。
  • etc/org.apache.karaf.features.cfg 配置文件中定义的功能存储库名称。

etc/org.apache.karaf.features.repos.cfg 定义了 "pre-installed/available" 功能仓库的列表:

################################################################################
#
#    Licensed to the Apache Software Foundation (ASF) under one or more
#    contributor license agreements.  See the NOTICE file distributed with
#    this work for additional information regarding copyright ownership.
#    The ASF licenses this file to You under the Apache License, Version 2.0
#    (the "License"); you may not use this file except in compliance with
#    the License.  You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#
################################################################################

#
# This file describes the features repository URL
# It could be directly installed using feature:repo-add command
#
enterprise=mvn:org.apache.karaf.features/enterprise/LATEST/xml/features
spring=mvn:org.apache.karaf.features/spring/LATEST/xml/features
cellar=mvn:org.apache.karaf.cellar/apache-karaf-cellar/LATEST/xml/features
cave=mvn:org.apache.karaf.cave/apache-karaf-cave/LATEST/xml/features
camel=mvn:org.apache.camel.karaf/apache-camel/LATEST/xml/features
camel-extras=mvn:org.apache-extras.camel-extra.karaf/camel-extra/LATEST/xml/features
cxf=mvn:org.apache.cxf.karaf/apache-cxf/LATEST/xml/features
cxf-dosgi=mvn:org.apache.cxf.dosgi/cxf-dosgi/LATEST/xml/features
cxf-xkms=mvn:org.apache.cxf.services.xkms/cxf-services-xkms-features/LATEST/xml
activemq=mvn:org.apache.activemq/activemq-karaf/LATEST/xml/features
jclouds=mvn:org.apache.jclouds.karaf/jclouds-karaf/LATEST/xml/features
openejb=mvn:org.apache.openejb/openejb-feature/LATEST/xml/features
wicket=mvn:org.ops4j.pax.wicket/features/LATEST/xml/features
hawtio=mvn:io.hawt/hawtio-karaf/LATEST/xml/features
pax-cdi=mvn:org.ops4j.pax.cdi/pax-cdi-features/LATEST/xml/features
pax-jdbc=mvn:org.ops4j.pax.jdbc/pax-jdbc-features/LATEST/xml/features
pax-jpa=mvn:org.ops4j.pax.jpa/pax-jpa-features/LATEST/xml/features
pax-web=mvn:org.ops4j.pax.web/pax-web-features/LATEST/xml/features
pax-wicket=mvn:org.ops4j.pax.wicket/pax-wicket-features/LATEST/xml/features
ecf=http://download.eclipse.org/rt/ecf/latest/site.p2/karaf-features.xml
decanter=mvn:org.apache.karaf.decanter/apache-karaf-decanter/LATEST/xml/features

您可以直接向 feature:repo-add 命令提供功能存储库名称。要安装,您可以安装 PAX JDBC:

karaf@root()> feature:repo-add pax-jdbc
Adding feature url mvn:org.ops4j.pax.jdbc/pax-jdbc-features/LATEST/xml/features

当您不提供可选 版本 参数时,Apache Karaf 将安装最新的功能存储库版本。您可以使用 version 参数指定 目标版本

karaf@root()> feature:repo-add pax-jdbc 1.3.0
Adding feature url mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.3.0/xml/features

不是提供 etc/org.apache.karaf.features.cfg 配置文件中定义的功能 存储库名称,而是直接向 feature:repo-add 命令提供功能存储库 URL:

karaf@root()> feature:repo-add mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.3.0/xml/features
Adding feature url mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.3.0/xml/features

默认情况下,feature:repo-add 命令只注册 features 仓库,它并不安装任何功能。如果指定了 -i 选项,则 feature:repo-add 命令注册 features 仓库并安装此功能存储库:

karaf@root()> feature:repo-add -i pax-jdbc

16.10.12.3. feature:repo-refresh

Apache Karaf 当您注册时解析功能存储库 XML(使用 feature:repo-add 命令或 FeatureMBean)。如果功能存储库 XML 更改,您必须指示 Apache Karaf 刷新功能存储库,以加载更改。

feature:repo-refresh 命令刷新功能存储库。

如果不使用参数,命令会刷新所有功能仓库:

karaf@root()> feature:repo-refresh
Refreshing feature url mvn:org.ops4j.pax.cdi/pax-cdi-features/0.12.0/xml/features
Refreshing feature url mvn:org.ops4j.pax.web/pax-web-features/4.1.4/xml/features
Refreshing feature url mvn:org.apache.karaf.features/standard/4.0.0/xml/features
Refreshing feature url mvn:org.apache.karaf.features/enterprise/4.0.0/xml/features
Refreshing feature url mvn:org.apache.karaf.features/spring/4.0.0/xml/features

您可以通过提供 URL 或功能存储库(以及可选的版本)来指定要刷新的功能存储库,而不是刷新所有功能存储库存储库:

karaf@root()> feature:repo-refresh mvn:org.apache.karaf.features/standard/4.0.0/xml/features
Refreshing feature url mvn:org.apache.karaf.features/standard/4.0.0/xml/features
karaf@root()> feature:repo-refresh pax-jdbc
Refreshing feature url mvn:org.ops4j.pax.jdbc/pax-jdbc-features/LATEST/xml/features

16.10.12.4. feature:repo-remove

feature:repo-remove 命令从注册的命令中删除功能存储库。

feature:repo-remove 命令需要一个参数:

  • 功能仓库名称(如 feature:repo-list 命令输出的 repository 列中显示)
  • features repository URL(如 feature:repo-list 命令输出的 URL 列中显示)
karaf@root()> feature:repo-remove org.ops4j.pax.jdbc-1.3.0
karaf@root()> feature:repo-remove mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.3.0/xml/features

默认情况下,feature:repo-remove 命令只从注册的目录中删除:它不会卸载 features 存储库提供的功能。

如果使用 -u 选项,则 feature:repo-remove 命令卸载 features 软件仓库描述的所有功能:

karaf@root()> feature:repo-remove -u org.ops4j.pax.jdbc-1.3.0

16.10.12.5. 功能:list

feature:list 命令列出所有可用功能(由不同注册的功能存储库提供):

Name                          | Version                          | Required | State       | Repository               | Description
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pax-cdi                       | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Provide CDI support
pax-cdi-1.1                   | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Provide CDI 1.1 support
pax-cdi-1.2                   | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Provide CDI 1.2 support
pax-cdi-weld                  | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Weld CDI support
pax-cdi-1.1-weld              | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Weld CDI 1.1 support
pax-cdi-1.2-weld              | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Weld CDI 1.2 support
pax-cdi-openwebbeans          | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | OpenWebBeans CDI support
pax-cdi-web                   | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Web CDI support
pax-cdi-1.1-web               | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Web CDI 1.1 support
...

如果要按字母顺序排列功能,可以使用 -o 选项:

karaf@root()> feature:list -o
Name                          | Version                          | Required | State       | Repository               | Description
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
deltaspike-core               | 1.2.1                            |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Apache Deltaspike core support
deltaspike-data               | 1.2.1                            |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Apache Deltaspike data support
deltaspike-jpa                | 1.2.1                            |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Apache Deltaspike jpa support
deltaspike-partial-bean       | 1.2.1                            |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Apache Deltaspike partial bean support
pax-cdi                       | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Provide CDI support
pax-cdi-1.1                   | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Provide CDI 1.1 support
pax-cdi-1.1-web               | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Web CDI 1.1 support
pax-cdi-1.1-web-weld          | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Weld Web CDI 1.1 support
pax-cdi-1.1-weld              | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Weld CDI 1.1 support
pax-cdi-1.2                   | 0.12.0                           |          | Uninstalled | org.ops4j.pax.cdi-0.12.0 | Provide CDI 1.2 support
...

默认情况下,feature:list 命令显示所有功能,无论其当前状态(已安装或未安装)。

使用 -i 选项只显示安装的功能:

karaf@root()> feature:list -i
Name            | Version | Required | State   | Repository     | Description
-------------------------------------------------------------------------------------------------------------------
aries-proxy     | 4.0.0   |          | Started | standard-4.0.0 | Aries Proxy
aries-blueprint | 4.0.0   | x        | Started | standard-4.0.0 | Aries Blueprint
feature         | 4.0.0   | x        | Started | standard-4.0.0 | Features Support
shell           | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Shell
shell-compat    | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Shell Compatibility
deployer        | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Deployer
bundle          | 4.0.0   | x        | Started | standard-4.0.0 | Provide Bundle support
config          | 4.0.0   | x        | Started | standard-4.0.0 | Provide OSGi ConfigAdmin support
diagnostic      | 4.0.0   | x        | Started | standard-4.0.0 | Provide Diagnostic support
instance        | 4.0.0   | x        | Started | standard-4.0.0 | Provide Instance support
jaas            | 4.0.0   | x        | Started | standard-4.0.0 | Provide JAAS support
log             | 4.0.0   | x        | Started | standard-4.0.0 | Provide Log support
package         | 4.0.0   | x        | Started | standard-4.0.0 | Package commands and mbeans
service         | 4.0.0   | x        | Started | standard-4.0.0 | Provide Service support
system          | 4.0.0   | x        | Started | standard-4.0.0 | Provide System support
kar             | 4.0.0   | x        | Started | standard-4.0.0 | Provide KAR (KARaf archive) support
ssh             | 4.0.0   | x        | Started | standard-4.0.0 | Provide a SSHd server on Karaf
management      | 4.0.0   | x        | Started | standard-4.0.0 | Provide a JMX MBeanServer and a set of MBeans in
wrap            | 0.0.0   | x        | Started | standard-4.0.0 | Wrap URL handler

16.10.12.6. 功能:install

feature:install 命令安装一个功能。

它需要 feature 参数。feature 参数是功能的名称,或者功能的名称/版本。如果只提供功能的名称(而非版本),则会安装最新版本。

karaf@root()> feature:install eventadmin

我们可以使用 -t--imulate 选项模拟 安装:它只显示其用途,但不能显示它:

karaf@root()> feature:install -t -v eventadmin
Adding features: eventadmin/[4.0.0,4.0.0]
No deployment change.
  Managing bundle:
    org.apache.felix.metatype / 1.0.12

您可以指定要安装的功能版本:

karaf@root()> feature:install eventadmin/4.0.0

默认情况下,feature:install 命令不详细。如果要提供有关 feature:install 命令执行的一些操作详情,您可以使用 -v 选项:

karaf@root()> feature:install -v eventadmin
Adding features: eventadmin/[4.0.0,4.0.0]
No deployment change.
Done.

如果功能包含已安装捆绑包(默认情况下,Apache Karaf)将刷新此捆绑包。现在,这个刷新可能会导致其他正在运行的应用程序出现问题。如果要禁用已安装的捆绑包的自动刷新,您可以使用 -r 选项:

karaf@root()> feature:install -v -r eventadmin
Adding features: eventadmin/[4.0.0,4.0.0]
No deployment change.
Done.

您可以使用 -s--no-auto-start 选项决定不启动功能安装的捆绑包:

karaf@root()> feature:install -s eventadmin

16.10.12.7. 功能:start

默认情况下,当您安装某个功能时,它会被自动安装。但是,您可以在 feature:install 命令中指定 -s 选项。

安装功能(启动或未启动)后,功能中定义的捆绑包提供的所有软件包都将可用,并可用于其他捆绑包中的 wiring。

启动功能时,会启动所有捆绑包,因此该功能也会公开服务。

16.10.12.8. 功能:stop

您还可以停止某个功能:这意味着功能提供的所有服务都将停止并从服务 registry 中删除。但是,软件包仍可用于 wiring(捆绑包处于已解析状态)。

16.10.12.9. 功能:uninstall

feature:uninstall 命令卸载一个功能。作为 feature:install 命令,feature:uninstall 命令需要 feature 参数。feature 参数是功能的名称,或者功能的名称/版本。如果只提供功能的名称(而非版本),则会安装最新版本。

karaf@root()> feature:uninstall eventadmin

功能解析程序在功能卸载过程中涉及到:如果其他功能没有使用,则可以卸载卸载功能所安装的功能。

16.10.13. deployer

您可以通过直接将文件拖放 在部署 文件夹中,"热部署"功能 XML。

Apache Karaf 提供了功能部署器。

当您丢弃部署文件夹中的功能 XML 时,功能部署器会发生:* 将功能 XML 注册为功能仓库。把 install 属性设置为 "auto" 的功能由功能部署器自动安装。

例如,在部署文件夹中丢弃以下 XML 将自动安装 feature1 和 feature2,但不安装 feature3:

<?xml version="1.0" encoding="UTF-8"?>
<features name="my-features" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.3.0 http://karaf.apache.org/xmlns/features/v1.3.0">

    <feature name="feature1" version="1.0" install="auto">
        ...
    </feature>

    <feature name="feature2" version="1.0" install="auto">
        ...
    </feature>

    <feature name="feature3" version="1.0">
        ...
    </feature>

</features>

16.10.14. JMX FeatureMBean

在 JMX 层上,您将有一个 MBean 专门用于管理特性和功能存储库: FeatureMBean。

FeatureMBean 对象名称为: org.apache.karaf:type=feature,name=*.

16.10.14.1. 属性

FeatureMBean 提供两个属性:

  • 功能是所有可用功能的表格数据集合。
  • repositories 是所有注册的功能存储库的表格数据集合。

Repositories 属性提供以下信息:

  • name 是功能存储库的名称。
  • URI 是此存储库的功能 XML 的 URI。
  • 功能是 功能 存储库提供的所有功能(名称和版本)的表格数据集。
  • 软件仓库 是功能存储库中"导入"的功能存储库集合。

Features 属性提供以下信息:

  • name 是功能的名称。
  • 版本是该功能的版本。
  • 安装为布尔值。如果为 true,代表当前安装该功能。
  • 捆绑包 (bundles)是功能中描述的所有捆绑包(bundles URL)的表格数据集。
  • 配置 是功能中描述的所有配置的表格数据集。
  • 配置文件是 功能中描述的所有配置文件的表格数据集合。
  • 依赖项是 功能中描述的所有依赖功能的表格数据集合。

16.10.14.2. 操作

  • addRepository(url) 使用 url 添加 features 存储库。url 可以是在 feature:repo-add 命令中的 名称
  • addRepository(url, install ) 添加带有 url 的 features 存储库,并在安装为 true 时自动安装所有捆绑包。url 可以是 feature:repo-add 命令中的 名称
  • 删除Repository(url) 将使用 url 删除 features 存储库。url 可以是在 feature:repo-remove 命令中的 名称
  • installFeature( name ) 使用名称 来安装功能。
  • installFeature( name, version) 使用名称和版本 来安装 该功能
  • installFeature(name, noClean, noRefresh) 安装带有 名称 而不在失败时清理捆绑包的功能,且没有刷新已安装的捆绑包。
  • installFeature(name, version, noClean, noRefresh)' 安装带有 'name 和 version 的功能,而不清理捆绑包(如果失败),而没有刷新已安装的捆绑包。
  • uninstallFeature(name) 使用名称 来卸载 该功能
  • uninstallFeature( name, version) 使用名称和版本 来卸载 该功能

16.10.14.3. 通知

FeatureMBean 发送两种类型的通知(您可以在其中订阅和响应):

  • 当功能存储库有变化(添加或删除)时。
  • 当功能更改(安装或卸载)时。

第 17 章 使用远程连接来管理容器

使用本地控制台管理容器并不有意义。Red Hat Fuse 可以通过多种方式远程管理容器。您可以使用远程容器的命令控制台或启动远程客户端。

17.1. 为远程访问配置容器

17.1.1. 概述

当您以默认模式或在 第 2.1.3 节 “以服务器模式启动运行时” 中启动 Red Hat Fuse 运行时,它会启用可从任何其他 Fuse 控制台访问的远程控制台。远程控制台提供本地控制台的所有功能,并允许远程用户对容器及其内部运行的服务进行完全控制。

注意

第 2.1.4 节 “以客户端模式启动运行时” 中运行时,Fuse 运行时会禁用远程控制台。

17.1.2. 配置独立容器以进行远程访问

SSH 主机名和端口号在 INSTALL_DIR/etc/org.apache.karaf.shell.cfg 配置文件中配置。更改远程访问的端口 显示了一个示例配置,它更改了用于 8102 的端口。

更改远程访问的端口

sshPort=8102
sshHost=0.0.0.0

17.2. 在远程连接和断开连接

连接到远程容器有两种替代方法。如果您已在运行 Red Hat Fuse 命令 shell,您必须调用控制台命令以连接到远程容器。或者,您可以直接在命令行中运行实用程序以连接到远程容器。

17.2.1. 从远程容器连接到独立容器

17.2.1.1. 概述

任何容器的命令控制台都可用于访问远程容器。使用 SSH,本地容器的控制台可连接到远程容器,并将功能作为远程容器的命令控制台连接。

17.2.1.2. 使用 ssh:ssh console 命令

您可以使用 ssh:ssh 控制台命令连接到远程容器的控制台。

ssh:ssh 命令语法

ssh:ssh -l username -P password -p port hostname

-l
用于连接到远程容器的用户名。使用具有 admin 特权的有效 JAAS 登录凭据。
-P
用于连接到远程容器的密码。
-p
用于访问所需容器的远程控制台的 SSH 端口。默认值为 8101。有关更改端口号的详情,请查看 第 17.1.2 节 “配置独立容器以进行远程访问”
主机名
运行远程容器的机器的主机名。有关更改主机名的详情,请查看 第 17.1.2 节 “配置独立容器以进行远程访问”
警告

我们建议您在 etc/users.properties 文件中自定义用户名和密码。

注意

如果您的远程容器部署在 Oracle VM Server for SPARC 实例中,则很可能默认的 SSH 端口值 8101 已被"逻辑域管理器守护进程"使用。在这种情况下,您需要重新配置容器的 SSH 端口,如 第 17.1.2 节 “配置独立容器以进行远程访问” 所述。

要确认您已连接到正确的容器,在 Karaf 控制台提示符处键入 shell:info,这将返回有关当前连接实例的信息。

17.2.1.3. 从远程控制台断开

要断开与远程控制台的连接,请在提示符下输入 logout 或按 Ctrl+D

您与远程容器断开连接,控制台一次将再次管理本地容器。

17.2.2. 使用客户端命令行实用程序连接到容器

17.2.2.1. 使用远程客户端

远程客户端允许您安全地连接到远程 Red Hat Fuse 容器,而无需在本地启动完整的 Fuse 容器。

例如,若要快速连接到在同一机器上在服务器模式下运行的 Fuse 实例,请打开命令提示符并运行 client[.bat] 脚本(位于 InstallDir/bin 目录中),如下所示:

client

通常,您可以提供一个主机名、端口、用户名和密码来连接远程实例。如果您在一个较大的脚本中使用客户端,例如在测试套件中,您可以附加控制台命令,如下所示:

client -a 8101 -h hostname -u username -p password shell:info

或者,如果省略 -p 选项,会提示您输入密码。

对于独立容器,使用具有 admin 特权的任何有效的 JAAS 用户凭证。

要显示客户端的可用选项,请键入:

client --help

Karaf 客户端帮助

Apache Felix Karaf client
  -a [port]     specify the port to connect to
  -h [host]     specify the host to connect to
  -u [user]     specify the user name
  -p [password] specify the password
  --help        shows this help message
  -v            raise verbosity
  -r [attempts] retry connection establishment (up to attempts times)
  -d [delay]    intra-retry delay (defaults to 2 seconds)
  [commands]    commands to run
If no commands are specified, the client will be put in an interactive mode

17.2.2.2. 远程客户端默认凭证

您可能会感到惊喜,发现您可以使用 bin/client 登录 Karaf 容器,而无需提供任何凭证。这是因为远程客户端程序已预先配置为使用默认凭证。如果没有指定凭证,远程客户端会自动尝试使用以下默认凭证(按顺序):

  • 默认的 SSH 密钥 10.10.10.2-abrt 尝试使用默认的 Apache Karaf SSH 密钥。允许此登录成功对应的配置条目在 etc/keys.properties 文件中被注释掉。
  • 默认用户名/密码凭证 abrt-abrt 尝试使用用户名和密码的 admin 组合登录。在 etc/users.properties 文件中,默认情况下,允许此登录成功对应的配置条目会被注释掉。

因此,如果您通过在 users.properties 中创建新用户,只需取消注释默认的 admin/admin 凭据,即可找到 bin/client 实用程序是否可以在不提供凭证的情况下登录。

重要

为安全起见,Fuse 在首次安装 Containers 时禁用了默认凭据(通过注释掉)。然而,如果您只取消注释这些默认凭据 而无需更改 默认密码或 SSH 公钥,那么您将在 Karaf 容器中开启安全漏洞。在生产环境中 不得 执行此操作。如果发现您可以使用 bin/client 在不提供凭证的情况下登录容器,这表明容器不安全,且您必须执行相应的步骤来在生产环境中修复

17.2.2.3. 从远程客户端控制台断开

如果您使用远程客户端打开远程控制台,而不是使用它传递命令,则需要断开连接。要断开与远程客户端控制台的连接,请在提示符下输入 logout 或按 Ctrl-D

客户端将断开连接并退出。

17.2.3. 使用 SSH 命令行实用程序连接到容器

17.2.3.1. 概述

您还可以使用 ssh 命令行实用程序(类似 UNIX 的操作系统中的标准实用程序)登录到 Red Hat Fuse 容器,其中验证机制基于公钥加密(必须首先在容器中安装公钥加密)。例如,如果容器配置为侦听 TCP 端口 8101,您可以按照如下所示登录:

ssh -p 8101 jdoe@localhost
重要

基于密钥的登录目前仅在独立容器上支持,不支持 Fabric 容器。

17.2.3.2. 先决条件

要使用基于密钥的 SSH 登录,必须满足以下先决条件:

17.2.3.3. 默认密钥位置

ssh 命令会在默认密钥位置自动查找私钥。建议您在默认位置安装您的密钥,因为它可让您明确指定该位置的问题。

在 *NIX 操作系统中,RSA 密钥对的默认位置是:

~/.ssh/id_rsa
~/.ssh/id_rsa.pub

在 Windows 操作系统中,RSA 密钥对的默认位置是:

C:\Documents and Settings\Username\.ssh\id_rsa
C:\Documents and Settings\Username\.ssh\id_rsa.pub
注意

Red Hat Fuse 仅支持 RSA 密钥。DSA 密钥 无法正常工作

17.2.3.4. 创建新的 SSH 密钥对

使用 ssh-keygen 程序生成 RSA 密钥对。打开新命令提示符并输入以下命令:

ssh-keygen -t rsa -b 2048

以上命令会生成 RSA 密钥,密钥长度为 2048 位。然后会提示您指定密钥对的文件名:

Generating public/private rsa key pair.
Enter file in which to save the key (/Users/Username/.ssh/id_rsa):

键入 return,将密钥对保存到默认位置。然后,系统将提示您输入密码短语:

Enter passphrase (empty for no passphrase):

您可以选择在此处输入密码短语或键入 returned 两次来选择不通过短语。

注意

如果您要运行 Fabric 控制台命令使用相同的密钥对,则建议您选择 不使用密码短语,因为 Fabric 不支持使用加密私钥。

17.2.3.5. 在容器中安装 SSH 公钥

要使用 SSH 密钥对登录 Red Hat JBoss Fuse 容器,您必须通过在 INSTALL_DIR/etc/keys.properties 文件中创建新用户条目,从而在容器中安装 SSH 公钥。此文件中的每个用户条目都出现在一行中,其格式如下:

Username=PublicKey,Role1,Role2,...

例如,如果您的公钥文件 ~/.ssh/id_rsa.pub,包含以下内容:

ssh-rsa AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7
gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnfqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCX
YFCPFSMLzLKSuYKi64QL8Fgc9QAAAnEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6Ewo
FhO3zwkyjMim4TwWeotifI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACB
AKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53Jj7uyk31drV2qxhIOsLDC9dGCWj4
7Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx jdoe@doemachine.local

您可以通过将以下条目添加到 InstallDir/etc/keys.properties 文件中(一行),以使用 admin 角色创建 jdoe 用户:

jdoe=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7
gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnfqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCX
YFCPFSMLzLKSuYKi64QL8Fgc9QAAAnEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6Ewo
FhO3zwkyjMim4TwWeotifI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACB
AKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53Jj7uyk31drV2qxhIOsLDC9dGCWj4
7Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,g:admingroup
重要

请勿在此处插入 id_rsa.pub 文件的整个内容。仅插入代表公钥本身的符号块。

17.2.3.6. 支持检查公钥身份验证

启动容器后,您可以通过运行 jaas:realms 控制台命令来检查公钥身份验证是否被支持,如下所示:

karaf@root()> jaas:realms
Index │ Realm Name │ Login Module Class Name
──────┼────────────┼─────────────────────────────────────────────────────-
1 │ karaf │ org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
2 │ karaf │ org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule
3 │ karaf │ org.apache.karaf.jaas.modules.audit.FileAuditLoginModule
4 │ karaf │ org.apache.karaf.jaas.modules.audit.LogAuditLoginModule
5 │ karaf │ org.apache.karaf.jaas.modules.audit.EventAdminAuditLoginModule
karaf@root()>

您应该看到是否已安装 PublickeyLoginModule。使用这个配置,您可以使用用户名/密码凭证或公钥凭证登录到容器。

17.2.3.7. 将 ssh 角色添加到 etc/keys.properties

etc/keys.properties 中定义的 admin 组 必须包含 ssh 角色,如下例所示:

#
# For security reason, the default auto-signed key is disabled.
# The user guide describes how to generate/update the key.
#
#karaf=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACBAKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53JjTuyk31drV2qxhIOsLDC9dGCWj47Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer,systembundles,ssh

如果 admingroup 的定义中没有包括 ssh 角色,您必须编辑 etc/keys.properties 并添加 ssh 角色。

17.2.3.8. 使用基于密钥的 SSH 登录

现在,您已准备好使用基于密钥的 SSH 实用程序登录容器。例如:

$ ssh -p 8101 jdoe@localhost
____          _   _   _       _     _____
|  _ \ ___  __| | | | | | __ _| |_  |  ___|   _ ___  ___
| |_) / _ \/ _` | | |_| |/ _` | __| | |_ | | | / __|/ _ \
|  _ <  __/ (_| | |  _  | (_| | |_  |  _|| |_| \__ \  __/
|_| \_\___|\__,_| |_| |_|\__,_|\__| |_|   \__,_|___/___|

  Fuse (7.x.x.fuse-xxxxxx-redhat-xxxxx)
  http://www.redhat.com/products/jbossenterprisemiddleware/fuse/

Hit '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.

Open a browser to http://localhost:8181/hawtio to access the management console

Hit '<ctrl-d>' or 'shutdown' to shutdown Red Hat Fuse.

karaf@root()>
注意

如果您使用加密的私钥,ssh 实用程序将提示您输入密码短语。

17.3. 停止远程容器

如果您使用 ssh:ssh 命令或远程客户端连接到远程控制台,您可以使用 osgi:shutdown 命令停止远程实例。

注意

在远程控制台中按 Ctrl+D 即可关闭远程连接并返回到本地 shell。

第 18 章 使用 Maven 构建

摘要

Maven 是一个开源构建系统,可从 Apache Maven 项目获取。本章介绍了一些基本的 Maven 概念,并描述了如何设置 Maven 来使用 Red Hat Fuse。在原则上,您可以使用任何构建系统来构建 OSGi 捆绑包。但强烈建议使用 Maven,因为红帽 Fuse 支持它。

18.1. Maven 目录结构

18.1.1. 概述

Maven 构建系统的一个最重要的原则是 Maven 项目中所有文件 的标准位置。此原则有几个优点。一个优点是 Maven 项目通常具有相同的目录布局,因此可以轻松地在项目中找到文件。另一个优点是,与 Maven 集成的各种工具 几乎不需要 初始配置。例如,Java 编译器知道它应当编译 src/main/java 下所有源文件并将其置于 target/classes 中。

18.1.2. 标准目录布局

例 18.1 “标准 Maven 目录布局” 展示了与构建 OSGi 捆绑项目相关的标准 Maven 目录布局的元素。另外,也会显示 Blueprint 配置文件( 不由 Maven 定义)的标准位置。

例 18.1. 标准 Maven 目录布局

ProjectDir/
    pom.xml
    src/
        main/
            java/
                ...
            resources/
                META-INF/

                OSGI-INF/
                    blueprint/
                        *.xml
        test/
            java/
            resources/
    target/
        ...
注意

可以覆盖标准目录布局,但这不是 Maven 中的建议做法。

18.1.3. pom.xml file

pom.xml 文件是当前项目的 Project Object Model(POM),其中包含有关如何构建当前项目的完整描述。pom.xml 文件可以完全包含,但频繁(用于更复杂的 Maven 项目);它可以从 父 POM 文件导入设置。

构建项目后,pom.xml 文件的副本将自动嵌入到生成的 JAR 文件中的以下位置:

META-INF/maven/groupId/artifactId/pom.xml

18.1.4. src 和目标目录

src/ 目录包含您要在开发项目期间工作的所有代码和资源文件。

target/ 目录包含构建的结果(通常是 JAR 文件),以及构建期间生成的所有中间文件。例如,执行构建后,target/classes/ 目录将包含资源文件和编译的 Java 类的副本。

18.1.5. 主目录和测试目录

src/main/ 目录包含构建工件所需的所有代码和资源。

src/test/ 目录包含所有代码和资源,用于针对已编译的工件运行单元测试。

18.1.6. Java 目录

每个 java/ 子目录均包含 Java 源代码(*.java 文件),其标准 Java 目录布局(即,目录路径名称镜像 Java 软件包名称的位置,其中 / 代替 . 字符)。src/main/java/ 目录包含捆绑源代码,src/test/java/ 目录包含单元测试源代码。

18.1.7. resources 目录

如果您有要包含在捆绑包中的配置文件、数据文件或 Java 属性,则这些文件应放在 src/main/resources/ 目录下。src/main/resources/ 下的文件和目录将复制到 Maven 构建进程生成的 JAR 文件的根目录中。

src/test/resources/ 下的文件仅在测试阶段使用,不会 复制到生成的 JAR 文件中。

18.1.8. 蓝图容器

OSGi R4.2 定义蓝图容器。Red Hat Fuse 内置了对 Blueprint 容器的支持,您可以通过在项目中包括 Blueprint 配置文件 OSGI-INF/blueprint/*.xml 来启用它。有关 Blueprint 容器的详情,请参考 第 12 章 OSGi 服务

18.2. 用于 Apache Karaf 的 BOM 文件

Maven Bill of Materials(BOM) 文件的目的是提供一组精心设计的 Maven 依赖项版本,从而为您保存每个 Maven 工件的版本,从而单独定义每个 Maven 工件的版本。

Apache Karaf 的 Fuse BOM 具有以下优点:

  • 定义 Maven 依赖项的版本,因此当您向 POM 添加依赖项时,您不需要指定版本。
  • 定义一组经过策展的依赖关系,这些依赖项是针对特定版本的 Fuse 完全测试和支持的。
  • 简化 Fuse 升级.
重要

红帽只支持由 Fuse BOM 定义的一组依赖项。

要将 Maven BOM 文件合并到 Maven 项目中,请在项目的 pom.xml 文件中指定 dependencyManagement 元素(或者,在父 POM 文件中可能),如下例所示:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project ...>
  ...
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <!-- configure the versions you want to use here -->
    <fuse.version>7.11.1.fuse-sb2-7_11_1-00022-redhat-00002</fuse.version>

  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.jboss.redhat-fuse</groupId>
        <artifactId>fuse-karaf-bom</artifactId>
        <version>${fuse.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  ...
</project>
注意

org.jboss.redhat-fuse BOM 是 Fuse 7 中的新内容,它旨在简化 BOM 版本。Fuse 快速入门和 Maven 层次结构仍使用旧的 BOM 风格,因为它们还没有重构为使用新的模式。BOMs 正确,您可以在 Maven 项目中使用它们。在即将发布的 Fuse 版本中,快速入门和 Maven archetypes 将重构为使用新的 BOM。

在使用依赖关系管理机制指定 BOM 后,可以在不 指定工件版本的情况下,将 Maven 依赖项添加到 POM 中。例如,要为 camel-velocity 组件添加一个依赖项,您要将以下 XML 片段添加到 POM 中的 dependencies 元素中:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-velocity</artifactId>
</dependency>

注意 version 元素是如何从这个依赖关系定义中省略的。

第 19 章 Maven Indexer 插件

Maven Indexer 插件需要 Maven Indexer 插件,以便其快速搜索 Maven Central 工件。

要部署 Maven Indexer 插件,请使用以下命令:

先决条件

在部署 Maven Indexer 插件前,请确定您已遵循在 Apache Karaf Preparing to Use Maven 部分的"安装"中的说明。

部署 Maven Indexer 插件

  1. 进入 Karaf 控制台,输入以下命令来安装 Maven Indexer 插件:

    features:install hawtio-maven-indexer
  2. 输入以下命令配置 Maven Indexer 插件:

    config:edit io.hawt.maven.indexer
    config:proplist
    config:propset repositories 'https://maven.oracle.com'
    config:proplist
    config:update
  3. 等待部署 Maven Indexer 插件。这可能需要几分钟时间。寻找日志选项卡中显示的消息,如下方所示的信息。

    Maven indexer 日志

部署 Maven Indexer 插件后,使用以下命令将进一步的外部 Maven 存储库添加到 Maven Indexer 插件配置:

config:edit io.hawt.maven.indexer
config:proplist
config:propset repositories external repository
config:proplist
config:update

第 20 章 Log

Apache Karaf 提供动态、强大的日志记录系统。

它支持:

  • OSGi 日志服务
  • Apache Log4j v1 和 v2 框架
  • Apache Commons Logging 框架
  • Logback 框架
  • SLF4J 框架
  • 原生 Java Util Logging 框架

这意味着应用程序可以使用任何日志记录框架,Apache Karaf 将使用中央日志系统来管理日志记录器、附加器等。

20.1. 配置文件

初始日志配置从 etc/org.ops4j.pax.logging.cfg 加载。

此文件是 标准 Log4j2 配置文件

找到不同的 Log4j2 元素:

  • 日志记录器
  • appenders
  • 布局

您可以在 文件中直接添加您自己的初始配置。

默认配置如下:

#
#  Copyright 2005-2018 Red Hat, Inc.
#
#  Red Hat licenses this file to you under the Apache License, version
#  2.0 (the "License"); you may not use this file except in compliance
#  with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
#  implied.  See the License for the specific language governing
#  permissions and limitations under the License.
#

#
# Internal Log4j2 configuration
#
log4j2.status = WARN
log4j2.verbose = false
log4j2.dest = out

#
# Common pattern layouts for appenders defined as reusable properties
# See https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout
# references will be replaced by felix.fileinstall
#
log4j2.pattern = %d{DEFAULT} | %-5.5p | %-20.20t | %-32.32c{1.} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
#log4j2.pattern = %d{DEFAULT} %-5.5p {%t} [%C.%M()] (%F:%L) : %m%n

#
# Appenders configuration
#

# JDBC Appender
log4j2.appender.jdbc.type = JDBC
log4j2.appender.jdbc.name = JdbcAppender
log4j2.appender.jdbc.tableName = EVENTS
log4j2.appender.jdbc.cs.type = DataSource
log4j2.appender.jdbc.cs.lazy = true
log4j2.appender.jdbc.cs.jndiName = osgi:service/jdbc/logdb
log4j2.appender.jdbc.c1.type = Column
log4j2.appender.jdbc.c1.name = DATE
log4j2.appender.jdbc.c1.isEventTimestamp = true
log4j2.appender.jdbc.c2.type = Column
log4j2.appender.jdbc.c2.name = LEVEL
log4j2.appender.jdbc.c2.pattern = %level
log4j2.appender.jdbc.c2.isUnicode = false
log4j2.appender.jdbc.c3.type = Column
log4j2.appender.jdbc.c3.name = SOURCE
log4j2.appender.jdbc.c3.pattern = %logger
log4j2.appender.jdbc.c3.isUnicode = false
log4j2.appender.jdbc.c4.type = Column
log4j2.appender.jdbc.c4.name = THREAD_ID
log4j2.appender.jdbc.c4.pattern = %thread
log4j2.appender.jdbc.c4.isUnicode = false
log4j2.appender.jdbc.c5.type = Column
log4j2.appender.jdbc.c5.name = MESSAGE
log4j2.appender.jdbc.c5.pattern = %message
log4j2.appender.jdbc.c5.isUnicode = false


# Console appender not used by default (see log4j2.rootLogger.appenderRefs)
log4j2.appender.console.type = Console
log4j2.appender.console.name = Console
log4j2.appender.console.layout.type = PatternLayout
log4j2.appender.console.layout.pattern = ${log4j2.pattern}

# Rolling file appender
log4j2.appender.rolling.type = RollingRandomAccessFile
log4j2.appender.rolling.name = RollingFile
log4j2.appender.rolling.fileName = ${karaf.data}/log/fuse.log
log4j2.appender.rolling.filePattern = ${karaf.data}/log/fuse-%i.log.gz
# uncomment to not force a disk flush
#log4j2.appender.rolling.immediateFlush = false
log4j2.appender.rolling.append = true
log4j2.appender.rolling.layout.type = PatternLayout
log4j2.appender.rolling.layout.pattern = ${log4j2.pattern}
log4j2.appender.rolling.policies.type = Policies
log4j2.appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
log4j2.appender.rolling.policies.size.size = 16MB
log4j2.appender.rolling.strategy.type = DefaultRolloverStrategy
log4j2.appender.rolling.strategy.max = 20

# Audit file appender
log4j2.appender.audit.type = RollingRandomAccessFile
log4j2.appender.audit.name = AuditRollingFile
log4j2.appender.audit.fileName = ${karaf.data}/security/audit.log
log4j2.appender.audit.filePattern = ${karaf.data}/security/audit.log.%i
log4j2.appender.audit.append = true
log4j2.appender.audit.layout.type = PatternLayout
log4j2.appender.audit.layout.pattern = ${log4j2.pattern}
log4j2.appender.audit.policies.type = Policies
log4j2.appender.audit.policies.size.type = SizeBasedTriggeringPolicy
log4j2.appender.audit.policies.size.size = 8MB

# OSGi appender
log4j2.appender.osgi.type = PaxOsgi
log4j2.appender.osgi.name = PaxOsgi
log4j2.appender.osgi.filter = *

#
# Loggers configuration
#

# Root logger
log4j2.rootLogger.level = INFO
log4j2.rootLogger.appenderRef.RollingFile.ref = RollingFile
log4j2.rootLogger.appenderRef.PaxOsgi.ref = PaxOsgi
log4j2.rootLogger.appenderRef.Console.ref = Console
log4j2.rootLogger.appenderRef.Console.filter.threshold.type = ThresholdFilter
log4j2.rootLogger.appenderRef.Console.filter.threshold.level = ${karaf.log.console:-OFF}
#log4j2.rootLogger.appenderRef.Sift.ref = Routing

# Spifly logger
log4j2.logger.spifly.name = org.apache.aries.spifly
log4j2.logger.spifly.level = WARN

# Security audit logger
log4j2.logger.audit.name = org.apache.karaf.jaas.modules.audit
log4j2.logger.audit.level = INFO
log4j2.logger.audit.additivity = false
log4j2.logger.audit.appenderRef.AuditRollingFile.ref = AuditRollingFile

# help with identification of maven-related problems with pax-url-aether
#log4j2.logger.aether.name = shaded.org.eclipse.aether
#log4j2.logger.aether.level = TRACE
#log4j2.logger.http-headers.name = shaded.org.apache.http.headers
#log4j2.logger.http-headers.level = DEBUG
#log4j2.logger.maven.name = org.ops4j.pax.url.mvn
#log4j2.logger.maven.level = TRACE

默认配置利用 out 文件附加程序定义 ROOT 日志记录器,其中的 INFO 日志级别。您可以将日志级别更改为任何 Log4j2 有效值。从最详细到最详细,您可以指定 DIB、DEBUG、INFOR、ERROR 或 FATAL。

OSGi 附加程序
osgi:* appender 是一个特殊的附加程序,用于将日志消息发送到 OSGi 日志服务。
stdout 附加程序
stdout 控制台附加器已预先配置,但默认情况下不启用。此附加程序允许您将日志消息直接显示到标准输出。如果您计划在服务器模式中运行 Apache Karaf(不带控制台)很有趣。

要启用它,您必须将 stdout 附加程序添加到 rootLogger 中:

log4j2.rootLogger=INFO, out, stdout, osgi:*
out appender
附加程序是默认值。这是一个滚动文件,可维护并轮转 10 个 1MB 日志文件。日志文件默认位于 data/log/fuse.log 中。
sift appender
默认情况下不启用 sift 附加程序。此附加程序允许您为每个部署的捆绑包有一个日志文件。默认情况下,日志文件名格式使用捆绑包符号名称(在 data/log 文件夹中)。您可以在运行时编辑此文件。Apache Karaf 重新加载文件,并且更改已生效。您不需要重启 Apache Karaf。Apache Karaf 使用另一个配置文件: etc/org.apache.karaf.log.cfg。此文件配置日志命令使用的日志服务(稍后请参阅)。
jdbc appender
jdbc appender 有一个 lazy 标志,当 true已启用)时,如果数据源不可用,日志不会添加到数据库中。但是,当 jndi、数据源或连接返回时,日志会重启。
log4j2.appender.jdbc.cs.lazy = true
重要

如果要避免丢失日志记录消息,我们也重新配置了紧急附加程序。

20.2. 命令

Apache Workbench 提供了一组命令来动态更改日志配置并查看日志内容,而不是更改 etc/org.ops4j.logging.cfg 文件,而是提供一组命令来动态更改日志配置并查看日志内容:

20.2.1. log:clear

log:clear 命令清除日志条目。

20.2.2. log:display

log:display 命令显示日志条目。

默认情况下,它显示 rootLogger 的日志条目:

karaf@root()> log:display
2015-07-01 19:12:46,208 | INFO  | FelixStartLevel  | SecurityUtils                    | 16 - org.apache.sshd.core - 0.12.0 | BouncyCastle not registered, using the default JCE provider
2015-07-01 19:12:47,368 | INFO  | FelixStartLevel  | core                             | 68 - org.apache.aries.jmx.core - 1.1.1 | Starting JMX OSGi agent

您还可以使用 logger 参数显示特定日志记录器的日志条目:

karaf@root()> log:display ssh
2015-07-01 19:12:46,208 | INFO  | FelixStartLevel  | SecurityUtils                    | 16 - org.apache.sshd.core - 0.12.0 | BouncyCastle not registered, using the default JCE provider

默认情况下会显示所有日志条目。如果从长时间运行 Apache Karaf 容器,这可能非常长。您可以使用 -n 选项限制要显示的条目数量:

karaf@root()> log:display -n 5
2015-07-01 06:53:24,143 | INFO  | JMX OSGi Agent   | core                             | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.framework.BundleStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.core:type=bundleState,version=1.7,framework=org.apache.felix.framework,uuid=5335370f-9dee-449f-9b1c-cabe74432ed1
2015-07-01 06:53:24,150 | INFO  | JMX OSGi Agent   | core                             | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.framework.PackageStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.core:type=packageState,version=1.5,framework=org.apache.felix.framework,uuid=5335370f-9dee-449f-9b1c-cabe74432ed1
2015-07-01 06:53:24,150 | INFO  | JMX OSGi Agent   | core                             | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.framework.ServiceStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.core:type=serviceState,version=1.7,framework=org.apache.felix.framework,uuid=5335370f-9dee-449f-9b1c-cabe74432ed1
2015-07-01 06:53:24,152 | INFO  | JMX OSGi Agent   | core                             | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.framework.wiring.BundleWiringStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.core:type=wiringState,version=1.1,framework=org.apache.felix.framework,uuid=5335370f-9dee-449f-9b1c-cabe74432ed1
2015-07-01 06:53:24,501 | INFO  | FelixStartLevel  | RegionsPersistenceImpl           | 78 - org.apache.karaf.region.persist - 4.0.0 | Loading region digraph persistence

您还可以使用 etc/org.apache.karaf.log.cfg 文件中的 size 属性限制存储和保留的条目数量:

#
# The number of log statements to be displayed using log:display. It also defines the number
# of lines searched for exceptions using log:display exception. You can override this value
# at runtime using -n in log:display.
#
size = 500

默认情况下,每个日志级别都以不同的颜色显示: ERROR/FATAL,代表代表,FATA 为红色,以 purple、INFO in cyan 等。您可以使用 --no-color 选项禁用颜色。

日志条目格式模式不使用 etc/org.ops4j.pax.logging.cfg 文件中定义的转换模式。默认情况下,它使用 etc/org.apache.karaf.log.cfg 中定义的 pattern 属性。

#
# The pattern used to format the log statement when using log:display. This pattern is according
# to the log4j2 layout. You can override this parameter at runtime using log:display with -p.
#
pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n

您还可以使用 -p 选项动态更改模式(对于一个执行):

karaf@root()> log:display -p "\%d - \%c - \%m\%n"
2015-07-01 07:01:58,007 - org.apache.sshd.common.util.SecurityUtils - BouncyCastle not registered, using the default JCE provider
2015-07-01 07:01:58,725 - org.apache.aries.jmx.core - Starting JMX OSGi agent
2015-07-01 07:01:58,744 - org.apache.aries.jmx.core - Registering MBean with ObjectName [osgi.compendium:service=cm,version=1.3,framework=org.apache.felix.framework,uuid=6361fc65-8df4-4886-b0a6-479df2d61c83] for service with service.id [13]
2015-07-01 07:01:58,747 - org.apache.aries.jmx.core - Registering org.osgi.jmx.service.cm.ConfigurationAdminMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.compendium:service=cm,version=1.3,framework=org.apache.felix.framework,uuid=6361fc65-8df4-4886-b0a6-479df2d61c83

这个模式是一个常规的 Log4j2 模式,您可以使用关键字(如 %d 代表日期),%c 代表类,%m 作为日志消息。

20.2.3. log:exception-display

log:exception-display 命令显示最后一次发生异常的情况。

对于 log:display 命令,log:exception-display 命令默认使用 rootLogger,但您可以使用 logger 参数指定一个 日志记录器

20.2.4. log:get

log:get 命令显示日志记录器的当前日志级别。

默认情况下,显示的日志级别是来自根日志记录器的日志级别:

karaf@root()> log:get
Logger                              │ Level
────────────────────────────────────┼──────
ROOT                                │ INFO
org.apache.aries.spifly             │ WARN
org.apache.karaf.jaas.modules.audit │ INFO
org.apache.sshd                     │ INFO

您可以使用 logger 参数指定特定的 日志记录器

karaf@root()> log:get ssh
INFO

logger 参数接受 ALL 关键字,以显示所有日志记录器的日志级别(作为列表)。

例如,如果您在 etc/org.ops4j.pax.logging.cfg 文件中定义了自己的日志记录器,如下所示:

log4j2.logger.my.name = MyLogger
log4j2.logger.my.level = DEBUG

您可以查看带有相应日志级别的日志记录器列表:

karaf@root()> log:get ALL
Logger                              │ Level
────────────────────────────────────┼──────
MyLogger                            │ DEBUG
ROOT                                │ INFO
org.apache.aries.spifly             │ WARN
org.apache.karaf.jaas.modules.audit │ INFO
org.apache.sshd                     │ INFO

log:list 命令是 log:get ALL 的别名。

20.2.5. log:log

log:log 命令允许您在日志中手动添加消息。在创建 Apache Karaf 脚本时,这很有趣的:

karaf@root()> log:log "Hello World"
karaf@root()> log:display
12:55:21.706 INFO [pipe-log:log "Hello World"] Hello World

默认情况下,日志级别为 INFO,但您可以使用 -l 选项指定不同的日志级别:

karaf@root()> log:clear
karaf@root()> log:log -l ERROR "Hello World"
karaf@root()> log:display
12:55:41.460 ERROR [pipe-log:log "Hello World"] Hello World

20.2.6. log:set

log:set 命令设置日志记录器的日志级别。

默认情况下,它会更改 rootLogger 的日志级别:

karaf@root()> log:set DEBUG
karaf@root()> log:get
Logger                              │ Level
────────────────────────────────────┼──────
ROOT                                │ DEBUG
...

您可以在 级别 后面使用 logger 参数指定特定的日志记录器:

karaf@root()> log:set INFO my.logger
karaf@root()> log:get my.logger
Logger    | Level
-----------------
my.logger | INFO

level 参数接受任何 Log4j2 日志级别: abrt、DEBUG、INFOR、WARN、ERROR、FATAL。

它还接受 DEFAULT 特殊关键字。

DEFAULT 关键字的目的是删除日志记录器的当前级别(仅是级别,没有删除 appender 之类的其他属性),以使用日志记录器父项的级别(日志记录器是层次结构)。

例如,您已定义了以下日志记录器(在 etc/org.ops4j.pax.logging.cfg 文件中):

rootLogger=INFO,out,osgi:*
my.logger=INFO,appender1
my.logger.custom=DEBUG,appender2

您可以更改 my.logger.custom logger 的级别:

karaf@root()> log:set INFO my.logger.custom

现在,我们已有:

rootLogger=INFO,out,osgi:*
my.logger=INFO,appender1
my.logger.custom=INFO,appender2

您可以使用 my.logger.custom logger 中的 DEFAULT 关键字来删除该级别:

karaf@root()> log:set DEFAULT my.logger.custom

现在,我们已有:

rootLogger=INFO,out,osgi:*
my.logger=INFO,appender1
my.logger.custom=appender2

这表示,在运行时,my.logger.custom 日志记录器使用其父 my.logger so INFO 的级别。

现在,如果我们将 DEFAULT 关键字与 my.logger 日志记录器搭配使用:

karaf@root()> log:set DEFAULT my.logger

我们有:

rootLogger=INFO,out,osgi:*
my.logger=appender1
my.logger.custom=appender2

因此,my.logger.custommy.logger 都使用父 rootLogger 的日志级别。

通过将 DEFAULT 关键字与 rootLogger 一起使用,它没有父项。

20.2.7. log:tail

log:taillog:display 完全相同,但它持续显示日志条目。

您可以使用与 log:display 命令相同的选项和参数。

默认情况下,它显示 rootLogger 中的条目:

karaf@root()> log:tail
2015-07-01 07:40:28,152 | INFO  | FelixStartLevel  | SecurityUtils                    | 16 - org.apache.sshd.core - 0.9.0 | BouncyCastle not registered, using the default JCE provider
2015-07-01 07:40:28,909 | INFO  | FelixStartLevel  | core                             | 68 - org.apache.aries.jmx.core - 1.1.1 | Starting JMX OSGi agent
2015-07-01 07:40:28,928 | INFO  | FelixStartLevel  | core                             | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering MBean with ObjectName [osgi.compendium:service=cm,version=1.3,framework=org.apache.felix.framework,uuid=b44a44b7-41cd-498f-936d-3b12d7aafa7b] for service with service.id [13]
2015-07-01 07:40:28,936 | INFO  | JMX OSGi Agent   | core                             | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.service.cm.ConfigurationAdminMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.compendium:service=cm,version=1.3,framework=org.apache.felix.framework,uuid=b44a44b7-41cd-498f-936d-3b12d7aafa7b

要从 log:tail 命令中退出,只需按 CTRL-C 键。

20.3. JMX LogMBean

您可以使用 log:* 命令执行所有您可以使用 log:* 命令执行的操作。

LogMBean 对象名称是 org.apache.karaf:type=log,name=*

20.3.1. 属性

  • level 属性是 ROOT 日志记录器的级别。

20.3.2. 操作

  • getLevel(logger) 以获取特定日志记录器的日志级别。由于此操作支持 ALL 关键字,它会返回一个 Map,其中包含每个日志记录器的级别。
  • 设置为Level(级别,日志记录器) 来设置特定日志记录器的日志级别。此操作支持 log:set 命令的 DEFAULT 关键字。

20.4. 高级配置

20.4.1. SIFT 日志记录

Fuse-Karaf 提供 Log4j2 sift appender 的 Log4j2 sift appender 和一个日志记录器的示例(在 $FUSE_HOME/etc/org.ops4j.pax.ops4j.pax.logging.cfg 文件中:

# Sift appender
log4j2.appender.mdc.type = Routing
log4j2.appender.mdc.name = SiftAppender
log4j2.appender.mdc.routes.type = Routes
# see: http://logging.apache.org/log4j/2.x/manual/appenders.html#Routes
log4j2.appender.mdc.routes.pattern = $\\{ctx:bundle.name}
log4j2.appender.mdc.routes.sift.type = Route
log4j2.appender.mdc.routes.sift.appender.type = RollingRandomAccessFile
log4j2.appender.mdc.routes.sift.appender.name = RollingFile
log4j2.appender.mdc.routes.sift.appender.fileName = ${karaf.data}/log/sift-$\\{ctx:bundle.name}.log
log4j2.appender.mdc.routes.sift.appender.filePattern = ${karaf.data}/log/sift-$\\{ctx:bundle.name}-%i.log.gz
log4j2.appender.mdc.routes.sift.appender.append = true
log4j2.appender.mdc.routes.sift.appender.layout.type = PatternLayout
log4j2.appender.mdc.routes.sift.appender.layout.pattern = ${log4j2.pattern}
log4j2.appender.mdc.routes.sift.appender.policies.type = Policies
log4j2.appender.mdc.routes.sift.appender.policies.size.type = SizeBasedTriggeringPolicy
log4j2.appender.mdc.routes.sift.appender.policies.size.size = 16MB
log4j2.appender.mdc.routes.sift.appender.strategy.type = DefaultRolloverStrategy
log4j2.appender.mdc.routes.sift.appender.strategy.max = 20
...
# sample logger using Sift appender
#log4j2.logger.example.name = org.apache.camel
#log4j2.logger.example.level = INFO
#log4j2.logger.example.appenderRef.SiftAppender.ref = SiftAppender

配置在 http://logging.apache.org/log4j/2.x/manual/appenders.html#RoutingAppender中描述

SIFT/Routing appender 的 Pattern 属性是可用于区分日志的目标位置。

可用的查找有不同的查找,如下所述 :http://logging.apache.org/log4j/2.x/manual/lookups.html

最重要的查找是 ctx one,它会在 ThreadContext 映射(a.k.a)中查找值(键)。MDC).

Fuse Karaf 提供的默认配置使用 ctx:bundle.name 作为模式,即:

lookup bundle.name key in MDC

bundle. prefix 键由 pax-logging 本身提供,有 3 个不同的值可供选择:

  • bundle.name == org.osgi.framework.Bundle.getSymbolicName()
  • bundle.id == org.osgi.framework.Bundle.getBundleId()
  • bundle.version == org.osgi.framework.Bundle.getVersion().toString()

但是,如果使用 MDC 支持创建 Camel 上下文(蓝色打印 XML DSL):

<camelContext id="my-context" xmlns="http://camel.apache.org/schema/blueprint" useMDCLogging="true">

在 MDC/ThreadContext 中会有一个更多密钥,然后将其用作 SIFT appender 配置中的模式:

  • Camel.exchangeId - 交换 ID
  • Camel.messageId - 消息 ID
  • Camel.correlationId - 与交换的关联 ID。例如,来自 Splitter EIP 的子消息
  • Camel.transactionKey - 转换交换的事务 ID。请注意 id 不是唯一的,而是其事务模板的 id,用于标记给定事务的事务边界。因此,我们决定将密钥命名为 transactionKey,而不是 transactionID 表明这一事实。
  • Camel.routeId - 路由的 id,当前正在路由。
  • Camel.breadcrumbId - 用于跨传输跟踪消息的唯一 ID。
  • Camel.contextId - 用于跟踪来自不同 camel 上下文的消息的 camel 上下文。

请查看 https://people.apache.org/~dkulp/camel/mdc-logging.html

例如,若要通过 Camel 的路由 ID 来区分日志目标文件,请使用:

log4j2.appender.mdc.routes.pattern = $\\{ctx:camel.routeId}
...
log4j2.appender.mdc.routes.sift.appender.fileName = ${karaf.data}/log/sift-$\\{ctx:camel.routeId}.log
log4j2.appender.mdc.routes.sift.appender.filePattern = ${karaf.data}/log/sift-$\\{ctx:camel.routeId}-%i.log.gz

更多事情 - 仅附加器配置还不够 - 必须将其附加到某些日志记录器。同样,配置示例包含:

# sample logger using Sift appender
#log4j2.logger.example.name = org.apache.camel
#log4j2.logger.example.level = INFO
#log4j2.logger.example.appenderRef.SiftAppender.ref = SiftAppender

(注意,log4j2.logger.example.appenderRef.SiftAppender.ref 属性的值应与 appender configuration 中的 log4j2.appender.mdc.name 的值匹配。

在这里,org.apache.camel 是日志记录器名称(或类别名称)。这完全与 Camel 日志中使用的值完全相同:端点。因此,如果您已有(在 Camel 路由中):

<to uri="log:org.apache.camel" />

日志记录可以正常工作。

另一个工作配置是:

<to uri="log:my-special-logger" />

和:

log4j2.logger.example.name = my-special-logger
log4j2.logger.example.level = DEBUG
log4j2.logger.example.appenderRef.SiftAppender.ref = SiftAppender

20.4.2. 过滤器

您可以将过滤器应用到 appender。过滤器评估每个日志事件,并确定是否将其发送到日志。

Log4j2 提供可用的过滤器。

注意

请参阅 Log4J 站点上的 过滤器,以获得到其中的综合视图。

20.4.3. 嵌套的附加器

嵌套的附加器是特殊的附加器,您可以使用 "inside" another appender。它允许您在一个附加器链之间创建某种"routing"。

最常用的"嵌套合规"附加器为:

  • AsyncAppender(org.apache.log4j2.AsyncAppender)会异步记录事件。此附加程序收集事件并将其分配到附加的所有附加者。
  • RewriteAppender(org.apache.log4j2.rewrite.RewriteAppender)在可能重新编写日志事件后将日志消息转发到另一个附加程序。

这种附加器接受 appender 定义中的 appenders 属性:

log4j2.appender.[appender-name].appenders=[comma-separated-list-of-appender-names]

例如,您可以创建一个名为 async 的 AsyncAppender,异步将日志消息分配给 JMS 附加程序:

log4j2.appender.async=org.apache.log4j2.AsyncAppender
log4j2.appender.async.appenders=jms

log4j2.appender.jms=org.apache.log4j2.net.JMSAppender
...

20.4.4. 错误处理程序

有时,附加程序可能会失败。例如,RollingFileAppender 尝试写入文件系统,但文件系统已满,或者 JMS 附加程序尝试发送消息,但 JMS 代理不可用。

日志记录可能很重要,因此务必要知道日志附加程序是否失败。

每个日志附加程序可以将错误处理委托给错误处理程序,从而有机会响应附加程序错误。

  • FailoverAppender(org.apache.log4j2.varia.FailoverAppender)允许在主附加程序失败时接管辅助附加程序。错误消息打印在 System.err 上,并记录在辅助附加程序中。
注意

有关 FailoverAppender 的更多信息,请转至 Log4j2 的 Apppender Page

您可以使用 appender 定义本身上的 errorhandler 属性定义您要用于每个 appender 的错误处理器:

log4j2.appender.[appender-name].errorhandler=[error-handler-class]
log4j2.appender.[appender-name].errorhandler.root-ref=[true|false]
log4j2.appender.[appender-name].errorhandler.logger-ref=[logger-ref]
log4j2.appender.[appender-name].errorhandler.appender-ref=[appender-ref]

20.4.5. OSGi 特定 MDC 属性

路由 附加器是 OSGi 的附加程序,可让您根据 MDC(Mapped Diagnostic Context)属性分割日志事件。

MDC 允许您区分不同的日志事件来源。

路由 附加器默认提供面向 OSGi 的 MDC 属性:

  • bundle.id 是捆绑包 ID
  • bundle.name 是捆绑包符号名称
  • bundle.version 是捆绑包版本

您可以使用这些 MDC 属性为每个捆绑包创建日志文件:

log4j2.appender.routing.type = Routing
log4j2.appender.routing.name = Routing
log4j2.appender.routing.routes.type = Routes
log4j2.appender.routing.routes.pattern = $$\\{ctx:bundle.name\\}
log4j2.appender.routing.routes.bundle.type = Route
log4j2.appender.routing.routes.bundle.appender.type = RollingRandomAccessFile
log4j2.appender.routing.routes.bundle.appender.name = Bundle-$\\{ctx:bundle.name\}
log4j2.appender.routing.routes.bundle.appender.fileName = ${karaf.data}/log/bundle-$\\{ctx:bundle.name\\}.log
log4j2.appender.routing.routes.bundle.appender.filePattern = ${karaf.data}/log/bundle-$\\{ctx:bundle.name\\}.log.%d{yyyy-MM-dd}
log4j2.appender.routing.routes.bundle.appender.append = true
log4j2.appender.routing.routes.bundle.appender.layout.type = PatternLayout
log4j2.appender.routing.routes.bundle.appender.policies.type = Policies
log4j2.appender.routing.routes.bundle.appender.policies.time.type = TimeBasedTriggeringPolicy
log4j2.appender.routing.routes.bundle.appender.strategy.type = DefaultRolloverStrategy
log4j2.appender.routing.routes.bundle.appender.strategy.max = 31

log4j2.rootLogger.appenderRef.Routing.ref = Routing

20.4.6. 加强 OSGi 堆栈追踪器

默认情况下,Apache Karaf 提供特殊的堆栈跟踪器,可添加一些 OSGi 特定信息。

在堆栈跟踪中,除了引发异常的类外,您还可以在每个堆栈追踪行末尾找到模式 [id:name:version],其中:

  • id 是捆绑包 ID
  • name 是捆绑包名称
  • 版本是捆绑包版本

诊断问题源非常有用。

例如,在以下 IllegalArgumentException 堆栈追踪中,我们可以查看有关异常来源的 OSGi 详情:

java.lang.IllegalArgumentException: Command not found:  *:foo
	at org.apache.felix.gogo.runtime.shell.Closure.execute(Closure.java:225)[21:org.apache.karaf.shell.console:4.0.0]
	at org.apache.felix.gogo.runtime.shell.Closure.executeStatement(Closure.java:162)[21:org.apache.karaf.shell.console:4.0.0]
	at org.apache.felix.gogo.runtime.shell.Pipe.run(Pipe.java:101)[21:org.apache.karaf.shell.console:4.0.0]
	at org.apache.felix.gogo.runtime.shell.Closure.execute(Closure.java:79)[21:org.apache.karaf.shell.console:4.0.0]
	at org.apache.felix.gogo.runtime.shell.CommandSessionImpl.execute(CommandSessionImpl.java:71)[21:org.apache.karaf.shell.console:4.0.0]
	at org.apache.karaf.shell.console.jline.Console.run(Console.java:169)[21:org.apache.karaf.shell.console:4.0.0]
	at java.lang.Thread.run(Thread.java:637)[:1.7.0_21]

20.4.7. 自定义附加器

您可以在 Apache Karaf 中使用您自己的附加器。

最简单的方法是将您的附件程序打包为 OSGi 捆绑包,并将其作为 org.ops4j.pax.logging.pax-logging-service 捆绑包的片段附加。

例如,您要创建 MyAppender

public class MyAppender extends AppenderSkeleton {
...
}

您将编译并打包成包含 MANIFEST 的 OSGi 捆绑包:

Manifest:
Bundle-SymbolicName: org.mydomain.myappender
Fragment-Host: org.ops4j.pax.logging.pax-logging-service
...

将捆绑包复制到 Apache Karaf 系统 文件夹中。系统 文件夹使用标准的 Maven 目录布局:groupId/artifactId/version。

etc/startup.properties 配置文件中,您可以在 pax-logging-service 捆绑包前在列表中定义捆绑包。

要重新加载系统捆绑包,您必须通过清理一个干净运行(清除 data 文件夹)来重启 Apache Karaf。现在,您可以直接在 etc/org.ops4j.pax.logging.cfg 配置文件中使用附加程序。

第 21 章 安全性

Apache Karaf 提供高级、灵活的安全系统,它采用 OSGi 兼容,由 JAAS(Java 认证和授权服务)提供支持。

它提供动态安全系统。

在内部使用 Apache Karaf 安全框架来控制对以下的访问:

  • OSGi 服务(包括在开发人员指南中)
  • 控制台命令
  • JMX 层
  • WebConsole

您的应用程序也可以使用安全框架(请参阅开发人员指南)。

21.1. Realms

Apache Karaf 可以管理多个域。realm 包含要用于此域中身份验证和授权的登录模块的定义。登录模块为域定义身份验证和授权。

jaas:realm-list 命令列出当前定义的 realm:

karaf@root()> jaas:realm-list
Index | Realm Name | Login Module Class Name
-----------------------------------------------------------------------------------
1     | karaf      | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
2     | karaf      | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule

您可以看到 Apache Karaf 提供名为 karaf 的默认域。

这个 realm 有两个登录模块:

  • PropertiesLoginModule 使用 etc/users.properties 文件作为用户、组、角色和密码的后端。此登录模块验证用户并返回用户的角色。
  • public keyLoginModule 特别由 SSHd 使用。它使用 etc/keys.properties 文件。此文件包含与每个用户关联的用户和一个公钥。

Apache Karaf 提供其他登录模块(请参阅《开发人员指南》以了解详细信息):

  • JDBCLoginModule 使用数据库作为后端
  • LDAPLoginModule 使用 LDAP 服务器作为后端
  • SyncopeLoginModule 使用 Apache Syncope 作为后端
  • OsgiConfigLoginModule 使用配置作为后端
  • Krb5LoginModule 使用 Kerberos 服务器作为后端
  • GSSAPILdapLoginModule 使用 LDAP 服务器作为后端,但将 LDAP 服务器身份验证委托给其他后端(通常是 Krb5LoginModule)

您可以使用 jaas:realm-manage 命令管理现有 realm、login 模块或创建自己的域。

21.1.1. 用户、组、角色和密码

正如我们看到的那样,默认情况下,Apache Karaf 使用 PropertiesLoginModule。

此登录模块使用 etc/users.properties 文件作为用户、组、角色和密码的存储。

初始 etc/users.properties 文件包含:

################################################################################
#
#    Licensed to the Apache Software Foundation (ASF) under one or more
#    contributor license agreements.  See the NOTICE file distributed with
#    this work for additional information regarding copyright ownership.
#    The ASF licenses this file to You under the Apache License, Version 2.0
#    (the "License"); you may not use this file except in compliance with
#    the License.  You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#
################################################################################

#
# This file contains the users, groups, and roles.
# Each line has to be of the format:
#
# USER=PASSWORD,ROLE1,ROLE2,...
# USER=PASSWORD,_g_:GROUP,...
# _g_\:GROUP=ROLE1,ROLE2,...
#
# All users, grousp, and roles entered in this file are available after Karaf startup
# and modifiable via the JAAS command group. These users reside in a JAAS domain
# with the name "karaf".
#
karaf = karaf,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer

我们可以在此文件中看到,默认情况下有一个用户 karaf。默认密码是 karaf

karaf 用户是一个组的成员: admingroup

个组始终以 g : 前缀。没有此前缀的条目是用户。

组定义了一组角色。默认情况下,admin group 定义组、adminmanagerviewer 角色。

这意味着 karaf 用户拥有 admingroup 定义的角色。

21.1.1.1. 命令

jaas:* 命令管理域中的域、用户、组、角色。

21.1.1.1.1. JAAS:realm-list

我们已在本节前面使用 jaas:realm-list

jaas:realm-list 命令列出每个域的域和登录模块:

karaf@root()> jaas:realm-list
Index | Realm Name | Login Module Class Name
-----------------------------------------------------------------------------------
1     | karaf      | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
2     | karaf      | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule

在这里有一个域(karaf),其中包含两个登录模块(PropertiesLoginModulePublickeyLoginModule)。

索引jaas:realm-manage 命令用来轻松识别我们要管理的 realm/login 模块。

21.1.1.1.2. JAAS:realm-manage

在 realm/login 模块编辑模式下的 jaas:realm-manage 命令切换,您可以在其中管理登录模块中的用户、组和角色。

要识别您要管理的域和登录模块,您可以使用 --index 选项。索引通过 jaas:realm-list 命令显示:

karaf@root()> jaas:realm-manage --index 1

另一种方法是使用 --realm--module 选项。domain 选项需要 realm 名称,-- module 选项需要 login 模块类名称:

karaf@root()> jaas:realm-manage --realm karaf --module org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
21.1.1.1.3. JAAS:user-list

当您处于编辑模式时,您可以使用 jaas:user-list 列出登录模块中的用户:

karaf@root()> jaas:user-list
User Name | Group      | Role
--------------------------------
karaf     | admingroup | admin
karaf     | admingroup | manager
karaf     | admingroup | viewer

您可以根据角色查看用户名和组。

21.1.1.1.4. JAAS:user-add

jaas:user-add 命令在当前编辑的登录模块中添加一个新用户(以及密码):

karaf@root()> jaas:user-add foo bar

要"提交"您的更改(这里添加用户),您必须执行 jaas:update 命令:

karaf@root()> jaas:update
karaf@root()> jaas:realm-manage --index 1
karaf@root()> jaas:user-list
User Name | Group      | Role
--------------------------------
karaf     | admingroup | admin
karaf     | admingroup | manager
karaf     | admingroup | viewer
foo       |            |

另外,如果要回滚用户添加,可以使用 jaas:cancel 命令。

21.1.1.1.5. jaas:user-delete

jaas:user-delete 命令从当前编辑的登录模块中删除用户:

karaf@root()> jaas:user-delete foo

jaas:user-add 命令类似,您必须使用 jaas:update 来提交您的更改(或者 jaas:cancel to rollback):

karaf@root()> jaas:update
karaf@root()> jaas:realm-manage --index 1
karaf@root()> jaas:user-list
User Name | Group      | Role
--------------------------------
karaf     | admingroup | admin
karaf     | admingroup | manager
karaf     | admingroup | viewer
21.1.1.1.6. jaas:group-add

jaas:group-add 命令可以为当前编辑的登录模块中的用户分配一个组(并最终创建组):

karaf@root()> jaas:group-add karaf mygroup
21.1.1.1.7. jaas:group-delete

jaas:group-delete 命令可从当前编辑的登录模块中的组中删除用户:

karaf@root()> jaas:group-delete karaf mygroup
21.1.1.1.8. jaas:group-role-add

jaas:group-role-add 命令在当前编辑的登录模块的组中添加一个角色:

karaf@root()> jaas:group-role-add mygroup myrole
21.1.1.1.9. jaas:group-role-delete

jaas:group-role-delete 命令可从当前编辑的登录模块的组中删除角色:

karaf@root()> jaas:group-role-delete mygroup myrole
21.1.1.1.10. JAAS:update

jaas:update 命令会在登录模块后端提交您的更改。例如,如果是 PropertiesLoginModule,只有执行 jaas:update 命令后才会更新 etc/users.properties

21.1.1.1.11. JAAS:cancel

jaas:cancel 命令回滚您的更改,不更新登录模块后端。

21.1.2. 密码加密

默认情况下,密码以明文形式存储在 etc/users.properties 文件中。

可以在 etc/org.apache.karaf.jaas.cfg 配置文件中启用加密:

################################################################################
#
#    Licensed to the Apache Software Foundation (ASF) under one or more
#    contributor license agreements.  See the NOTICE file distributed with
#    this work for additional information regarding copyright ownership.
#    The ASF licenses this file to You under the Apache License, Version 2.0
#    (the "License"); you may not use this file except in compliance with
#    the License.  You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#
################################################################################

#
# Boolean enabling / disabling encrypted passwords
#
encryption.enabled = false

#
# Encryption Service name
#   the default one is 'basic'
#   a more powerful one named 'jasypt' is available
#       when installing the encryption feature
#
encryption.name =

#
# Encryption prefix
#
encryption.prefix = {CRYPT}

#
# Encryption suffix
#
encryption.suffix = {CRYPT}

#
# Set the encryption algorithm to use in Karaf JAAS login module
# Supported encryption algorithms follow:
#   MD2
#   MD5
#   SHA-1
#   SHA-256
#   SHA-384
#   SHA-512
#
encryption.algorithm = MD5

#
# Encoding of the encrypted password.
# Can be:
#   hexadecimal
#   base64
#
encryption.encoding = hexadecimal

如果启用 encryption.enabled y 被设置为 true,则启用密码加密。

启用加密后,密码在第一次登录时会加密。加密的密码带有 \{CRYPT\} 的前缀和后缀。要重新加密密码,您可以以明文( etc/users.properties 文件中)重置密码,而无需 \{CRYPT\} 前缀和后缀。Apache Karaf 将检测此密码处于明确状态(因为它没有带有 \{CRYPT\} 前缀并后缀),然后再次对其进行加密。

etc/org.apache.karaf.jaas.cfg 配置文件允许您定义高级加密机制:

  • encryption.prefix 属性将前缀定义为"flag"密码进行加密。默认值为 \{CRYPT\}。
  • encryption.suffix 属性定义"flag"密码加密的后缀。默认值为 \{CRYPT\}。
  • encryption.algorithm 属性定义用于加密的算法(digest)。可能的值有 MD2MD5SHA-1SHA-256SHA-384SHA-512。默认值为 MD5
  • encryption.encoding 属性定义加密密码的编码。可能的值有 十六进制base64。默认值为 十六进制

21.1.3. 通过密钥管理身份验证

对于 SSH 层,chronyc 支持通过密钥进行身份验证,允许在不提供密码的情况下登录。

SSH 客户端(因此 bin/client 由 Karaf 本身提供),或者任何 ssh 客户端(如 OpenSSH)使用公钥/私钥对,它将标识自己在 Karaf SSHD(服务器端)上的 public/私钥对。

允许连接的密钥存储在 etc/keys.properties 文件中,其格式如下:

user=key,role

默认情况下,Packspace 允许 karaf 用户的密钥:

# karaf=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACBAKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53JjTuyk31drV2qxhIOsLDC9dGCWj47Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,admin
注意

出于安全考虑,这个密钥已被禁用。我们鼓励每个客户端创建密钥对,并更新 etc/keys.properties 文件。

创建密钥对的最简单方法是使用 OpenSSH。

您可以使用以下命令创建密钥对:

ssh-keygen -t dsa -f karaf.id_dsa -N karaf

您现在有公钥和私钥:

-rw-------  1 jbonofre jbonofre    771 Jul 25 22:05 karaf.id_dsa
-rw-r--r--  1 jbonofre jbonofre    607 Jul 25 22:05 karaf.id_dsa.pub

您可以在 etc/keys.propertieskaraf.id_dsa.pub 文件的内容中复制:

karaf=AAAAB3NzaC1kc3MAAACBAJLj9vnEhu3/Q9Cvym2jRDaNWkATgQiHZxmErCmiLRuD5Klfv+HT/+8WoYdnvj0YaXFP80phYhzZ7fbIO2LRFhYhPmGLa9nSeOsQlFuX5A9kY1120yB2kxSIZI0fU2hy1UCgmTxdTQPSYtdWBJyvO/vczoX/8I3FziEfss07Hj1NAAAAFQD1dKEzkt4e7rBPDokPOMZigBh4kwAAAIEAiLnpbGNbKm8SNLUEc/fJFswg4G4VjjngjbPZAjhkYe4+H2uYmynry6V+GOTS2kaFQGZRf9XhSpSwfdxKtx7vCCaoH9bZ6S5Pe0voWmeBhJXi/Sww8f2stpitW2Oq7V7lDdDG81+N/D7/rKDD5PjUyMsVqc1n9wCTmfqmi6XPEw8AAACAHAGwPn/Mv7P9Q9+JZRWtGq+i4pL1zs1OluiStCN9e/Ok96t3gRVKPheQ6IwLacNjC9KkSKrLtsVyepGA+V5j/N+Cmsl6csZilnLvMUTvL/cmHDEEhTIQnPNrDDv+tED2BFqkajQqYLgMWeGVqXsBU6IT66itZlYtrq4v6uDQG/o=,admin

然后,指定客户端使用 karaf.id_dsa 私钥:

bin/client -k ~/karaf.id_dsa

或 ssh

ssh -p 8101 -i ~/karaf.id_dsa karaf@localhost

21.1.4. RBAC

Apache Karaf 使用角色来控制对资源的访问:它是 RBAC(基于角色的访问控制)系统。

角色可用于控制:

  • 了解 OSGi 服务
  • 访问控制台(控制命令的执行)
  • 访问 JMX(MBeans 和/或操作)
  • 访问 WebConsole

21.1.4.1. OSGi 服务

有关 OSGi 服务 RBAC 支持的详细信息,请参阅开发人员指南。

21.1.4.2. 控制台(Console)

控制台 RBAC 支持对 OSGi 服务 RBAC 的分类。实际上,在 Apache Karaf 中,所有控制台命令都定义为 OSGi 服务。

控制台命令名称采用 scope:name 格式。

ACL(Access Lists)在 etc/org.apache.karaf.command.acl.<scope>.cfg 配置文件中定义,其中 &lt ;scope&gt; 是命令范围。

例如,我们可以通过创建 etc/org.apache.karaf.command.feature.cfg 配置文件来定义对功能的 ACL :* 命令。在这个 etc/org.apache.karaf.command.acl.feature.cfg 配置文件中,我们可以设置:

list = viewer
info = viewer
install = admin
uninstall = admin

在这里,我们定义了 该功能:listfeature:info 命令可由具有 viewer 角色的用户执行,而 feature:installfeature:uninstall 命令只能由具有 admin 角色的用户执行。请注意,admin 组中的用户也具有查看器角色,因此能够完成所有操作。

Apache Karaf 命令 ACL 可以使用 (在指定命令范围内)控制访问:

  • 命令名称 regex(如 name = role
  • 命令名称和选项或参数值 regex(例如,名称[/.[/.[0-90-9][0-9]+./] = role 只能执行名称,且值为 100 以上)

命令名称和选项/参数都支持完全匹配或正则表达式匹配。

默认情况下,Apache Karaf 定义以下命令 ACL:

  • etc/org.apache.karaf.command.acl.bundle.cfg 配置文件定义 bundle:* 命令的 ACL。此 ACL 仅将 bundle:* 命令的执行限制为具有 admin 角色的用户,而非系统捆绑包的 bundle:* 命令可由具有 manager 角色的用户执行。
  • etc/org.apache.karaf.command.acl.config.cfg 配置文件定义了 config:* 命令的 ACL。此 ACL 使用 jmx.acl.*org.apache.karaf.command.acl.*org.apache.karaf.service.acl.* 配置 PID 将 config:* 命令限制为具有 admin 角色的用户。对于其他配置 PID,具有 manager 角色的用户可以执行 config:* 命令。
  • etc/org.apache.karaf.command.acl.feature.cfg 配置文件定义 feature:* 命令的 ACL。只有具有 admin 角色的用户才能执行 feature:installfeature:uninstall 命令。其它 功能:* 命令可以由任何用户执行。
  • etc/org.apache.karaf.command.acl.jaas.cfg 配置文件定义了 jaas:* 命令的 ACL。只有具有 admin 角色的用户才能执行 jaas:update 命令。其它 jaas:* 命令可由任何用户执行。
  • etc/org.apache.karaf.command.acl.kar.cfg 配置文件为 kar:* 命令定义 ACL。只有具有 admin 角色的用户才能执行 kar:installkar:uninstall 命令。其他 kar:* 命令可由任何用户执行。
  • etc/org.apache.karaf.command.acl.shell.cfg 配置文件定义了 shell 的 ACL:* 和 "direct" 命令。只有具有 admin 角色的用户才能执行 shell:editshell:execshell:new、和 shell:java 命令。其他 shell:* 命令可以由任何用户执行。

您可以更改这些默认 ACL,并为附加命令范围添加您自己的 ACL(例如,如 etc/org.apache.karaf.command.acl.cluster.cfg for Apache Karaf Ce llar 等/org.apache.karaf.command.acl.camel.cfg )。

您可以通过编辑 etc/system.properties 中的 karaf.secured.services 属性来微调命令 RBAC 支持:

#
# By default, only Karaf shell commands are secured, but additional services can be
# secured by expanding this filter
#
karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*))

21.1.4.3. JMX

与控制台命令类似,您可以定义 ACL(AccessLists)到 JMX 层。

JMX ACL 在 etc/jmx.acl<ObjectName>.cfg 配置文件中定义,其中 <ObjectName > 是一个 MBean 对象名称(例如 org.apache.karaf.bundle 代表 org.apache.karaf;type=Bundle MBean)。

etc/jmx.acl.cfg 是最通用的配置文件,在找不到特定配置文件时使用。它包含"全局"ACL 定义。

JMX ACL 可以使用 (在 JMX MBean 旁边)控制访问:

  • 操作名称 regex(如 operation* = role
  • 操作参数值 regex(如 operation(java.lang.String, int)[/([1-4])?[0-9]/,/.*/] = role

默认情况下,Apache Karaf 定义以下 JMX ACL:

  • etc/jmx.acl.org.apache.karaf.bundle.cfg 配置文件定义 org.apache.karaf:type=bundle MBean 的 ACL。此 ACL 限制 setStartLevel()start()stop()update() 操作,仅适用于具有 admin 角色的用户。其他操作可以由具有 manager 角色的用户执行。
  • etc/jmx.acl.org.apache.karaf.config.cfg 配置文件定义 org.apache.karaf:type=config MBean 的 ACL。此 ACL 对 jmx.acl*org.apache.karaf.command.acl*org.apache.karaf.service.acl* 配置 PID 仅限具有 admin 角色的用户进行限制。其他操作可以由具有 manager 角色的用户执行。
  • etc/jmx.acl.org.apache.karaf.security.jmx.cfg 配置文件定义 org.apache.karaf:type=security,area=jmx MBean 的 ACL。这个 ACL 限制了具有 viewer 角色的用户调用 canInvoke() 操作。
  • etc/jmx.acl.osgi.compendium.cm.cfg 配置文件为 osgi.compendium:type=cm MBean 定义 ACL。这个 ACL 会限制 jmx.acl*org.apache.karaf.command.acl*org.apache.karaf.service.acl* 配置 PID 的配置 PID。其他操作可以由具有 manager 角色的用户执行。
  • etc/jmx.acl.java.lang.Memory.cfg 配置文件为核心 JVM 内存 MBean 定义 ACL。这个 ACL 限制了 gc 操作只对具有 manager 角色的用户的调用。
  • etc/jmx.acl.cfg 配置文件是最通用的文件。此处定义的 ACL 不在其他特定 ACL 匹配时使用(根据特定 ACL,它在另一个 MBean 特定 etc/jmx.acl.*.cfg 配置文件中定义的 ACL)。list*(), get*() 是*() 操作,可由具有 viewer 角色的用户执行。set*() 和所有其他 *() 操作都可以由具有 admin 角色的用户执行。

21.1.4.4. WebConsole

默认情况下,Apache Karaf WebConsole 不可用。要启用它,您必须安装 webconsole 功能:

karaf@root()> feature:install webconsole

WebConsole 不支持现在不支持精细的 RBAC,如 console 或 JMX。

具有 admin 角色的所有用户可以登录 WebConsole 并执行任何操作。

21.1.5. SecurityMBean

Apache Karaf 提供了一个 JMX MBean,可检查当前用户是否可以调用给定的 MBean 和/或操作。

canInvoke() 操作获取当前用户的角色,并检查一个角色是否可以调用 MBean 和/或操作,最后使用一个给定参数值。

21.1.5.1. 操作

  • 如果当前用户可以使用 objectName 调用 MBean,则 canInvoke(objectName) 会返回 true
  • 如果当前用户可以使用 objectName 的 MBean 调用 operation methodName,则 canInvoke(objectName, methodName) 会返回 true
  • 如果当前用户可以使用带有 objectName 的参数类型参数Types 数组调用 operation methodName,则 canInvoke(objectName, methodName, argumentTypes ) 返回 true
  • canInvoke(bulkQuery) 返回一个表格数据,如果 canInvoketruefalse,则返回包括为 bulkQuery tabular data 的每个操作的表格数据。

21.1.6. 安全供应商

有些应用程序需要特定的安全供应商可用,如 [BouncyCastle|http://www.bouncycastle.org]。

JVM 对使用这些 jars 的一些限制施加一些限制:它们必须经过签名并在引导类路径中可用。

部署这些提供程序的一种方法是将它们放到 $JAVA_HOME/jre/lib/ext 的 JRE 文件夹中,再修改安全策略配置($JAVA_HOME/jre/lib/security/java.security.security),才能注册这些提供程序。

虽然此方法可以正常工作,但它具有全局效果,但需要您相应地配置所有服务器。

Apache Karaf 提供配置额外安全提供程序的简单方法:* 将供应商 jar 放在 lib/ext * 中修改 etc/config.properties 配置文件以添加以下属性

org.apache.karaf.security.providers = xxx,yyy

此属性的值是要注册的供应商类名称的逗号分隔列表。

例如,要添加 bouncycastle 安全供应商,您可以定义:

org.apache.karaf.security.providers = org.bouncycastle.jce.provider.BouncyCastleProvider

另外,您可能想要从系统捆绑包中提供对这些供应商的类的访问权限,以便所有捆绑包都可以访问它们。

这可以通过修改同一配置文件中的 org.osgi.framework.bootdelegation 属性来实现:

org.osgi.framework.bootdelegation = ...,org.bouncycastle*

法律通告

Copyright © 2023 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.