OSGi 中的 Akka

    示例项目

    你可以查看「」示例项目,以了解其在实践中的使用情况。

    OSGi」是一个成熟的基于组件的系统打包和部署标准。它具有与项目 Jigsaw(最初计划为 JDK 1.8)相似的功能,但它有更强大的设施来支持遗留 Java 代码。这就是说,尽管 Jigsaw-ready 模块需要对大多数源文件进行重大更改,有时还需要对整个应用程序的结构进行修改,但 OSGi 可以用于将几乎任何 Java 代码模块化为 JDK 1.2,通常对二进制文件没有任何更改。

    这些遗留功能是 OSGi 的主要优势和主要弱点。OSGi 的创建者早就意识到,实现者不太可能急于在现有 JAR 中支持 OSGi 元数据。在 JRE 中已经有一些新的概念需要学习,而直接使用 J2EE 管理良好的团队的附加价值并不明显。已经出现了“包装”二进制 JAR 的工具,因此它们可以作为捆绑包使用,但此功能仅在有限的情况下使用。这里的为一个应用程序可能会有「80% 的复杂性可以通过 20% 的配置解决」,但这足以给 OSGi 名声大振。

    本文档旨在为大家提供使用 Akka 所需的基础知识,要获得比这里提供的更多的信息,「」是值得探索的。

    OSGi 应用程序的核心组件和结构

    当加载一个Bundle时,需要为每个Bundle实例化 Java ClassLoader 的专门实现。每个类加载器读取manifest条目,并在容器单例中发布功能(以Bundle-Exports的形式)和需求(作为Bundle-Imports),以供其他Bundle发现。通过这些类加载器将导入与跨Bundle导出匹配的过程是解析过程,这是 OSGi 容器中Bundle的生命周期 FSM 中六个离散步骤之一:

    1. RESOLVED:已解决的Bundle是满足其需求(导入)的Bundle,解析意味着可以启动一个Bundle
    2. STARTING:启动的Bundle可以被其他Bundle使用。对于以其他方式完全关闭已解析Bundle的应用程序,这里的含义是必须按照深度优先搜索所有要启动的Bundle的顺序启动它们。当一个启动时,Bundle中任何暴露的生命周期接口都会被调用,从而使Bundle有机会启动自己的服务端点和线程。
    3. ACTIVE:一旦一个Bundle的生命周期接口无错误地返回,Bundle就被标记为活动的。
    4. STOPPING:正在停止的Bundle调用Bundle的停止生命周期,并在完成时转换回RESOLVED状态。在STARTING时创建的任何长时间运行的服务或线程都应在调用Bundle的停止生命周期时关闭。
    5. UNINSTALLEDBundle只能从INSTALLED状态转换到此状态,这意味着在停止之前无法卸载它。

    注意这个 FSM 中对生命周期接口的依赖性。虽然没有要求Bundle发布这些接口或接受此类回调,但生命周期接口提供main()方法的语义,并允许Bundle启动和停止长时间运行的服务,如 REST 页面服务、ActorSystem、群集等。

    其次,请注意,在考虑需求和能力时,将它们与存储库依赖性等同是一个常见的误解,这可能在 Maven 或 Ivy 中发现。虽然它们提供了类似的实用功能,但是 OSGi 有几种并行类型的依赖关系(如 Blueprint Services),这些依赖关系不容易映射到存储库功能上来。实际上,核心规范将这些设施留给使用中的容器。反过来,一些容器有工具从存储库元数据生成应用程序加载描述符。

    结合对Bundle生命周期的理解,OSGi 开发人员必须注意有时引入的意外行为。这些行为通常都在 JVM 规范中,但是有些意外的情况,仍然会导致失败。

    除非像类那样显式导出,否则资源不会在Bundle之间共享。这种情况的常见情况是,getClass().getClassLoader().getResources("foo")将返回名为foo的类路径上的所有文件。getResources()方法只从当前的类加载器返回资源,并且由于每个Bundle都有单独的类加载器,因此资源文件(如配置)不再能够以这种方式进行搜索。

    配置 OSGi 框架

    要在 OSGi 环境中使用 Akka,必须对容器进行配置,使org.osgi.framework.bootdelegation属性将包委托给引导类加载器,而不是通过普通的 OSGi 类空间解析它。

    Akka 只支持严格限制在单个 OSGi 包中使用ActorSystem,其中该Bundle包含或导入所有 Actor 系统的需求。这意味着不建议将ActorSystem作为一个服务来提供,Actor 可以通过其他Bundle动态部署到该服务上,ActorSystem及其包含的 Actor 在这种方式下不应该以是动态的。ActorRef可以安全地暴露在其他Bundle中。

    Activator

    要在 OSGi 环境中引导 Akka,可以使用akka.osgi.ActorSystemActivator类方便地设置ActorSystem

    1. import akka.actor.{ ActorSystem, Props }
    2. import org.osgi.framework.BundleContext
    3. import akka.osgi.ActorSystemActivator
    4. class Activator extends ActorSystemActivator {
    5. def configure(context: BundleContext, system: ActorSystem): Unit = {
    6. // optionally register the ActorSystem in the OSGi Service Registry
    7. registerService(context, system)
    8. val someActor = system.actorOf(Props[SomeActor], name = "someName")
    9. someActor ! SomeMessage
    10. }

    英文原文链接:.