【问题标题】:How to scale an OSGi Service with Declarative Services correctly?如何使用声明式服务正确扩展 OSGi 服务?
【发布时间】:2021-06-13 15:43:53
【问题描述】:

项目描述:

我有一个简单的 OSGi 演示项目。域是具有多种传感器类型的气象站。每个传感器将其数据发送到气象站。通过 API,数据通过图表在网站上公开和可视化。

目标:

例如:我目前有三种不同的传感器类型。一种用于测量风速、温度和湿度。 气象站应该有多个风传感器实例 (Cardinality.MULTIPLE)。

现状:

目前我正在通过创建一个 WindSpeedSensor 和一个 WindSpeedAdvancedSensor 服务来解决这个问题。我已经为 Apache Karaf 实现了一个自定义命令,我可以在其中向我的服务发送特定的配置命令。因此,传感器可以配置为在特定范围内生成测量值。

所需条件:

最佳解决方案是通过 Karaf 命令行启动额外的 WindSpeedSensor 实例。 WeatherStation 类应该不需要人工WindSpeedSensors 来实现多服务的目标。

问题:

我怎样才能做到这一点?我是 OSGi 和声明式服务的新手,我很好奇 OSGi 专家如何解决这个问题。提前感谢您的时间和反馈。

【问题讨论】:

    标签: java osgi declarative-services


    【解决方案1】:

    您可以使用Factory Configurations(请参阅https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-deployment)。对于工厂 pid 下的每个配置,DS 都会创建一个组件配置。这允许根据 Configuration Admin 中的出厂配置多次创建一个组件。

    【讨论】:

    • 请至少提供一个简短的工作示例以及必须完成的最低配置。 osgi 规范并没有真正的帮助。
    【解决方案2】:

    我只将 OSGi 与 Karaf 一起使用,因此对于其他环境可能会有所不同。

    如果您需要为每个配置文件提供 OSGi 服务,您可以使用声明性服务注释设置此类服务,例如这样。

    import org.osgi.framework.BundleContext;
    import org.osgi.service.component.annotations.Activate;
    import org.osgi.service.component.annotations.Component;
    import org.osgi.service.component.annotations.ConfigurationPolicy;
    import org.osgi.service.metatype.annotations.Designate;
    
    import com.example.service.config.ExampleServiceConfig;
    
    @Component(
        immediate = true, service = ExampleService.class, 
        configurationPolicy = ConfigurationPolicy.REQUIRE,
        configurationPid = "com.example.service.ExampleService"
    )
    @Designate(ocd = ExampleServiceConfig.class, factory = true)
    public class ExampleService {
    
        @Activate
        public void onServiceActivate(BundleContext context, ExampleServiceConfig config){
            System.out.println(config.hello_message());
        }
    }
    

    然后为服务定义类型安全的配置,例如:

    import org.osgi.service.metatype.annotations.ObjectClassDefinition;
    
    @ObjectClassDefinition(name = "ExampleService Configuration")
    public @interface ExampleServiceConfig {
     
        String hello_message() default "hello world";
        String osgi_jndi_service_name() default "unique.service.name";
    }
    

    由于单例配置使用<configurationPid>.cfg 之类的文件名,工厂配置使用<configurationPid>-<InstanceName>.cfg 格式,因此要在上面创建ExampleService 的两个实例,您可以创建例如以下配置:

    com.example.service.ExampleService-InstanceA.cfg

    hello.message=Hello from Instance A
    osgi.jdni.service.name=InstanceA
    

    com.example.service.ExampleService-InstanceB.cfg

    hello.message=Hello from Instance B
    osgi.jdni.service.name=InstanceB
    

    至少在 Karaf 中,这将创建两个 ExampleService 实例和两个具有某种唯一 guid(而不是实例名称)的配置。要引用特定的服务实例,您可以使用引用注释中的目标属性。

    @Reference(
        target = "(osgi.jdni.service.name=InstanceA)"
    )
    ExampleService exampleService;
    

    【讨论】:

      猜你喜欢
      • 2019-09-25
      • 2012-04-27
      • 1970-01-01
      • 2010-10-15
      • 2013-10-09
      • 2018-05-20
      • 1970-01-01
      • 1970-01-01
      • 2012-10-01
      相关资源
      最近更新 更多