我正在使用Apache 4.1.1和Karaf C业力。我写了两捆。第一个包提供类型为ITrackerManager的服务。第二个包有一个引用ITrackerManager的组件。我的最终目标是见证第二个包中的组件成功地获得对第一个包中的ITrackerManager服务的引用,该服务运行在另一个节点上。这都是我探索分布式OSGi的一部分。
当我安装第二个包时,实际发生的情况是,它被安装了,但是由于缺少服务引用而无法激活。我一定是做错了测试。关于如何演示我的最终目标的任何想法;节点B上的包中的组件成功地在Node A?上使用服务
到目前为止,我是如何进行测试的。
Node 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实例。这两个实例都能看到对方。现在我只想将第一个包安装到Node A上。为此,我将包安装到集群中,然后具体地从Node中删除它。
Node 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
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太棒了。第一个包已经从Node中删除,但仍然显示在集群中。两个节点都同意,我的服务现在只在节点A上可用(因为包已从节点B中删除)。现在,我将只在节点B上加载我的第二个包。这就是我遇到问题的地方。我不使用集群: bundle - install命令加载第二个包,因为我不希望它在Node 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上的所需服务。不幸的是,这种情况并没有发生。相反,我会收到错误消息,说明有未解决的需求。它似乎表现为DOSGI不可用。如果我在同一个节点上安装了两个包,那么第二个包将在没有任何错误的情况下激活。如果您有任何见解,我将不胜感激。
发布于 2017-07-12 19:26:36
我的问题是两方面的。
我的API定义了两个接口。
该API包已安装到集群中,因此它在所有节点上都可用。我的Service有一个ITrackerManager的具体实现。当该包在节点A上本地安装时,集群: service -list命令正确地显示Node有一个类型为ITrackerManager的服务。
我的客户机包有一个ITracker的具体实现,它引用了ITrackerManager,它安装在Node上。ITracker实例在其激活方法中所做的第一件事就是调用ITrackerManager.addTracker(this)。应该发生的是Node上的ITracker实例将自己提供给运行在Node上的ITrackerManager。最初这失败了,因为ITracker是不可串行化的。一旦解决了这个问题,我就开始在Node上看到classNotFound异常。
节点A试图在本地反序列化ITracker实例。它试图放弃一个没有在本地定义的具体类(TheirTracker),它只在客户机包中的节点B上定义。这次失败了。
所以正常的命名空间规则是适用的。尽管节点B上的客户端包引用了运行在包节点A中的服务,但节点A中的服务包不能创建(即反序列化)仅存在于节点B上的客户端包中的类的实例。
我切换了我的接口,这样ITrackerManager方法就不会出现ITracker争论。相反,它需要一个字符串。在DOSGi上调用该方法很好。
虽然我理解这个问题存在的原因,但这破坏了我希望在DOSGi中使用的核心能力。我希望客户能够在中央控制器注册,中央控制器将积极控制他们。这不起作用,因为即使客户端实现了中央控制器正在寻找的接口,但是特定的序列化在中央控制器上失败。客户机具体类存在于中央控制器未知的名称空间中,因此客户端无法成功地将自己传递给中央控制器。
这必须是实现我在DSOGi中所寻找的功能的一种方法,而不必使每个多个客户端都成为导出的DSOGi服务。有什么想法吗?
https://stackoverflow.com/questions/44976444
复制相似问题