0

我正在使用 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 上结束。所以我使用普通的 bundle:install 命令安装我的第二个包。这会导致关于不满足参考的错误。

节点 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

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

4

1 回答 1

0

我的问题有两个。

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

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

我的 API 定义了两个接口。

  • 追踪器
  • 跟踪管理器

该 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 服务。有任何想法吗?

于 2017-07-12T19:26:36.450 回答