asadmin 是 GlassFish 的命令行工具,它提供了一系列子命令,使用 asadmin
可以让你完成 Glassfish
的所有管理任务。
使用 asadmin
的子命令 start-domain 可以启动 GlassFish
。下面将描述 GlassFish
启动过程的主要流程。先从 asadmin
命令的执行开始。
asadmin
命令的入口是 org.glassfish.admin.cli.AsadminMain, 包含在 ${AS_INSTALL_LIB}/client/appserver-cli.jar
包中。
AsadminMain
执行的主要流程如下:
其中的一些关键点:
-
调用
CLICommand.getCommand()
获得启动服务器的子命令。asadmin
的所有子命令的都继承自com.sun.enterprise.admin.cli.CLICommand ,从下列目录或 Jar 中加载:-
${com.sun.aas.installRoot}/lib/asadmin
-
${com.sun.aas.installRoot}/modules/admin-cli.jar
-
-
所有子命令的执行都是调用
CLICommand.execute(String... argv)
。 -
启动
GlassFish
的子命令实现类为StartDomainCommand,内部调用GFLauncher.launch()
启动服务器。 -
最终 GFLauncher 使用 ProcessBuilder 启动一个新的进程,就是 GlassFish 的主进程。这个新进程的入口是com.sun.enterprise.glassfish.bootstrap.ASMain。
另外,如果设置了 verbose
或 watchdog
参数,作为父进程的asadmin
不会退出,一直等到 GlassFish 运行结束:
// If verbose, hang around until the domain stops
if (getInfo().isVerboseOrWatchdog()) {
wait(glassFishProcess);
}
下面分析 GlassFish
主进程的启动流程。
GlassFish
主进程的入口是 com.sun.enterprise.glassfish.bootstrap.ASMain 的 main
方法,启动过程的主要流程如下:
启动过程比较复杂,但主要步骤很清晰:
- 使用 RuntimeBuilder 创建 GlassFishRuntime
- 使用 GlassFishRuntime 创建 GlassFish 实例
- 调用
GlassFish.start()
启动Glassfish
实例
创建 GlassFishRuntime
的主要步骤包括:
- 创建 RuntimeBuilder
- 创建并初始化 OSGi Framework
- 加载 OSGi bundles
- 启动 OSGi Framework
- 启动 bundles 中的 BundleActivator
- 在 HK2Main 的启动过程中查找并注册 HK2 modules
在创建 GlassFishRuntime
的过程中,OSGiGlassFishRuntimeBuilder 会创建并初始化 OSGi Framework ,然后使用 BundleProvisioner 的 installBundles() 方法向 OSGi 安装 GlassFish 的所有 bundles。
BundleProvisioner
从哪里找到要加载的 bundles?config/osgi.properties
文件中的 glassfish.osgi.auto.install
属性定义了 OSGi bundles 的加载路径。BundleProvisioner.discoverJars()
方法会扫描这些路径,发现需要加载的 Jar 包。
在完成 bundles 的加载后,OSGiGlassFishRuntimeBuilder
会调用 Framework.start()
启动 OSGi Framework。 Framework 的启动过程中,bundles 中的 BundleActivator 会被启动。其中两个重要的 BundleActivator
是:
GlassFishMainActivator 启动过程中会向 OSGi 中注册 EmbeddedOSGiGlassFishRuntime。
HK2Main 会创建 ModulesRegistry。ModulesRegistry 是 HK2 的关键组件,HK2 中的 modules 都注册在这里。在 OSGi 环境下,ModulesRegistry 的具体实现类是 OSGiModulesRegistryImpl,它会从所有 bundle Jar 的 META-INF/hk2-locator
目录中查找并注册该 bundle 包含的 HK2 modules。
ModulesRegistry
和 HK2Main
都会注册为 OSGi 的 service。
通过GlassFishRuntime.newGlassFish()
创建出 GlassFish 实例,这个过程主要做了两件事:
- 创建出 HK2 的 ServiceLocator
- 从 ServiceLocator 获取 ModuleStartup
在 EmbeddedOSGiGlassFishRuntime
中使用 ModulesRegistry.newServiceLocator() 创建出 ServiceLocator
,然后从 ServiceLocator
获取 ModuleStartup。在 GlassFish 启动场景获取的是 ModuleStartup
的一个具体实现 AppServerStartup。
ServiceLocator
是 HK2 service 的注册表,它提供了一系列获取 HK2 service 的方法。
HK2 Module 和 Service 的关系可以看作是容器和内容的关系。Module(容器)包含了一组 Service(内容),并且负责将这些 Service 注册到 ServiceLocator
中。当一个 Module 被初始化时,它的所有 Service 都会被注册到 ServiceLocator
中,然后这些 Service 就可以被其他 Service 查找和使用。
最后将 AppServerStartup
和 ServiceLocator
作为构造函数的参数,创建出 GlassFish
实例。
使用 GlassFish.start()
启动 Glassfish
实例。其中最关键的步骤是调用 AppServerStartup.start()
,分级启动 HK2 的 service。HK2 的 service 可以指定启动级别,级别越低,越先启动。
AppServerStartup.start()
运行完成,所有 service 启动,Glassfish 完成启动并运行。