使用 Apache Karaf Cellar 的分布式 OSGi 示例 - 客户端bundle无法激活,因为找不到分布式服务



我正在使用Apache Karaf 4.1.1和Karaf Cellar。我写了两捆。第一个捆绑包提供 ITrackerManager 类型的服务。第二个捆绑包有一个引用 ITrackerManager 的组件。我的最终目标是见证第二个捆绑包中的组件成功获取对在不同节点上运行的第一个捆绑包中的 ITrackerManager 服务的引用。这是我探索分布式OSGi的一部分。

当我安装第二个捆绑包时,实际发生的事情是它已安装,但由于缺少服务引用而无法激活。我一定是测试不正确。关于我将如何展示我的最终目标的任何想法;节点 B 上的捆绑包中的组件成功使用节点 A 上的服务?


以下是我到目前为止运行测试的方式。

节点 A

karaf@root()> cluster:node-list
| Id                | Alias | Host Name    | Port
--+-------------------+-------+--------------+-----
x | 159.4.251.58:5701 |       | 159.4.251.58 | 5701
| 159.4.251.58:5702 |       | 159.4.251.58 | 5702

节点 B

karaf@root()> cluster:node-list
| Id                | Alias | Host Name    | Port
--+-------------------+-------+--------------+-----
| 159.4.251.58:5701 |       | 159.4.251.58 | 5701
x | 159.4.251.58:5702 |       | 159.4.251.58 | 5702

目前为止,一切都好。我在计算机上运行两个 karaf 实例。两个实例相互可见。现在我想仅将第一个捆绑包安装到节点 A 上。为此,我将捆绑包安装到群集中,然后专门将其从节点 B 中删除。

节点 A

karaf@root()> cluster:bundle-install -s default mvn:myCompany/dosgi-example-part1/1.0-SNAPSHOT
karaf@root()> cluster:bundle-list default
Bundles in cluster group default
ID | State    | Lvl | Located       | Blocked | Version        | Name
---+----------+-----+---------------+---------+----------------+--------------------------------------------------------------
0 | Active   |     | cluster/local |         | 5.6.2          | System Bundle
...
67 | Active   |     | cluster/local       |         | 1.0.0.SNAPSHOT | Distributed OSGi Example Part 1
karaf@root()> cluster:service-list
Service Class             | Provider Node
--------------------------+------------------
myCompany.ITrackerManager | 159.4.251.58:5701
| 159.4.251.58:5702

还是好看的。我的捆绑包位于群集中,在节点 A(此时为节点 B)上是本地的,并且该服务被群集识别,并且在节点 A 和节点 B 上都可用。现在从节点 B 中删除捆绑包。

节点 B

karaf@root()> cluster:bundle-list default
Bundles in cluster group default
ID | State    | Lvl | Located       | Blocked | Version        | Name
---+----------+-----+---------------+---------+----------------+-------------------------------------------------------------
67 | Active   |     | cluster/local |         | 1.0.0.SNAPSHOT | Distributed OSGi Example Part 1
karaf@root()> bundle:list
START LEVEL 100 , List Threshold: 50
ID | State  | Lvl | Version        | Name
---+--------+-----+----------------+-----------------------------------------------
75 | Active |  80 | 1.0.0.SNAPSHOT | Distributed OSGi Example Part 1
karaf@root()> bundle:uninstall 75
karaf@root()> cluster:bundle-list default
Bundles in cluster group default
ID | State    | Lvl | Located       | Blocked | Version        | Name
---+----------+-----+---------------+---------+----------------+--------------------------------------------------------------
67 | Active   |     | cluster |         | 1.0.0.SNAPSHOT | Distributed OSGi Example Part 1
karaf@root()> cluster:service-list
Service Class             | Provider Node
--------------------------+------------------
myCompany.ITrackerManager | 159.4.251.58:5701

非常好。第一个捆绑包已从节点 B 中删除,但仍显示为在群集中。两个节点都同意我的服务现在仅在节点 A 上可用(因为捆绑包已从节点 B 中删除)。现在,我将仅在节点 B 上加载我的第二个捆绑包。这就是我遇到问题的地方。我不使用 cluster:bundle-install 命令加载第二个捆绑包,因为我不希望它最终出现在节点 A 上。因此,我使用普通的捆绑包:安装命令安装我的第二个捆绑包。这会导致有关未满足引用的错误。

节点 B

karaf@root()> bundle:install -s mvn:otherCompany/dosgi-example-part2/1.0-SNAPSHOT
Bundle ID: 76
Error executing command: Error installing bundles:
Unable to start bundle mvn:otherCompany/dosgi-example-part2/1.0-SNAPSHOT: org.osgi.framework.BundleException: Unable to resolve otherCompany.dosgi-example-part2 [76](R 76.0): missing requirement [otherCompany.dosgi-example-part2 [76](R 76.0)] osgi.wiring.package; (&(osgi.wiring.package=myCompany)(version>=1.0.0)(!(version>=2.0.0))) Unresolved requirements: [[otherCompany.dosgi-example-part2 [76](R 76.0)] osgi.wiring.package; (&(osgi.wiring.package=myCompany)(version>=1.0.0)(!(version>=2.0.0)))]
karaf@root()> bundle:list
START LEVEL 100 , List Threshold: 50
ID | State     | Lvl | Version        | Name
---+-----------+-----+----------------+-----------------------------------------------------------------------------------------------------
76 | Installed |  80 | 1.0.0.SNAPSHOT | Distributed OSGi Example Part 2

原来如此。我只在节点 B 上安装第二个捆绑包,期望它能够成功使用仅驻留在节点 A 上的所需服务。不幸的是,这并没有发生。相反,我收到错误消息,指出存在未解决的要求。它似乎表现得好像 DOSGI 不可用。如果我在同一节点上安装两个捆绑包,则第二个捆绑包将激活而不会出现任何错误。如果您有任何见解,将不胜感激。

我的问题是双重的。

  1. 通过DOSGI发送的内容需要可序列化。 就我而言,我在远程服务上调用了一个接受参数的方法。该参数是在通用 API 中定义的类类型。该类类型不可序列化。一旦我使它可序列化,它就开始出现不同的错误。这让我想到...

  2. 普通命名空间规则适用。我将在下面详细说明。

我的 API 定义了两个接口。

  • ITracker
  • ITrackerManager

该 API 捆绑包已安装到群集中,因此可在所有节点上使用。我的服务包有一个具体的ITrackerManager实现。当该捆绑包本地安装在节点 A 上时,cluster:service-list 命令会正确显示节点 A 具有 ITrackerManager 类型的服务。

我的客户端捆绑包有一个具体的 ITracker 实现,它引用了安装在节点 B 上的 ITrackerManager。ITracker实例在其激活方法中做的第一件事就是调用ITrackerManager.addTracker(this)。应该发生的事情是,节点 B 上的 ITracker 实例将自身提供给在节点 A 上运行的 ITrackerManager。最初失败了,因为 ITracker 不可序列化。一旦解决了这个问题,我就开始在节点A上看到classNotFound异常。

节点 A 正在尝试在本地反序列化 ITracker 实例。它试图去分离一个未在本地定义的具体类(TheirTracker),它仅在客户端捆绑包中的节点B上定义。这失败了。

因此,正常的命名空间规则适用。即使节点 B 上的客户端捆绑包引用了在捆绑节点 A 中运行的服务,节点 A 中的服务捆绑包也无法创建(即反序列化)仅存在于节点 B 上的客户端捆绑包中的类的实例。

我切换了我的界面,以便ITrackerManager方法不接受ITracker参数。相反,它需要一个字符串。通过DOSGi调用该方法可以正常工作。

虽然我理解为什么存在这个问题,但这破坏了我希望与DOSGi一起使用的核心功能。我希望客户能够向中央控制器注册,该控制器将主动控制它们。这是行不通的,因为即使客户端实现了中央控制器要查找的接口,特定的序列化也会在中央控制器上失败。客户端具体类存在于中央控制器未知的命名空间中,因此客户端无法成功地将自身传递给中央控制器。

这必须是实现我在 DSOGi 中寻找的内容的一种方式,而无需使多个客户端中的每个客户端都成为导出的 DSOGi 服务。有什么想法吗?

最新更新