1. Sbt 启动器架构

Sbt 启动器架构 

sbt 启动器是一种机制,通过该机制可以从 Ivy 加载模块并在 JVM 中执行。它抽象了获取和缓存 jar 的机制,允许用户专注于他们想要的应用程序,并控制其版本。

启动器的主要目标是获取应用程序的配置(主要是 Ivy 坐标和主类)并启动应用程序。启动器会解析 Ivy 模块,缓存所需的运行时 jar,并启动应用程序。

sbt 启动器为应用程序提供了在应用程序完成时加载另一个应用程序、正常退出或从另一个应用程序内部加载其他应用程序的方式。

sbt 启动器提供以下核心功能

  • 模块解析
  • 类加载器缓存和隔离
  • 文件锁定
  • 服务发现和隔离

模块解析 

sbt 启动器的主要目的是解析应用程序并运行它们。这通过 [app] 配置部分完成。有关如何配置模块解析的更多信息,请参阅[启动器配置][Launcher-Configuration]。

模块解析使用 Ivy 依赖管理库完成。此库还支持从 Maven 仓库加载工件。

类加载器缓存和隔离 

sbt 启动器的类加载结构与在标准 Java 机制中启动应用程序不同。启动器加载的每个应用程序都有自己的类加载器。此类加载器是应用程序使用的 Scala 类加载器的子类。Scala 类加载器可以访问启动器本身的所有 xsbti.* 类。

以下是从 sbt 启动的应用程序中的类加载器布局示例。

image

在此图中,加载了三个不同的应用程序。其中两个使用相同版本的 Scala(2.9.2)。在这种情况下,sbt 可以为这些应用程序共享相同的类加载器。这具有以下优点:由于共享类加载器,对 Scala 类执行的任何 JIT 优化可以在应用程序之间重复使用。

缓存 

sbt 启动器在 Ivy 自己的缓存之上创建了一个二级缓存。这有助于将应用程序与不稳定版本(如 -SNAPSHOT)导致的错误隔离开来。对于任何启动的应用程序,启动器都会创建一个目录来存储其所有 jar。以下是一个示例布局。

锁定 

除了提供二级缓存之外,启动器还提供了一种安全进行基于文件的锁定的机制。启动器直接在两个地方使用它

  1. 锁定引导目录。
  2. 确保已定位的服务器最多只有一个活动进程。

此功能需要支持锁定的文件系统。它通过 xsbti.GlobalLock 接口公开。

  • 注意:这既是线程锁又是文件锁。我们不仅限制了对单个进程的访问,还限制了该进程中单个线程的访问。*

服务发现和隔离 

启动器还提供了一种机制来确保服务器只有一个实例正在运行,同时在客户端请求时动态启动它。这是通过启动器上的 --locate 标志完成的。当启动器使用 --locate 标志启动时,它将执行以下操作

  1. 锁定配置的服务器锁定文件。
  2. 读取服务器属性以查找先前服务器的 URI。
  3. 如果端口仍在监听连接请求,则在命令行上打印此 URI。
  4. 如果端口未监听,则启动一个新服务器并在命令行上写入 URI。
  5. 释放所有锁并关闭。

配置的 server.lock 文件用于防止多个服务器运行。sbt 本身使用它来防止在任何给定的项目目录上运行多个服务器,方法是将 server.lock 配置为 ${user.dir}/.sbtserver