概述

JBoss 7/WildFly 以 domain 模式启动时会启动多个 JVM。比如例如以下通过启动脚本启动 domain 模式:

./domain.sh

启动后我们查看进程:

[kylin@localhost tdump]$ jps -l
23655 /home/kylin/work/eap/jboss-eap-6.1/jboss-modules.jar
23671 /home/kylin/work/eap/jboss-eap-6.1/jboss-modules.jar
23736 /home/kylin/work/eap/jboss-eap-6.1/jboss-modules.jar

我们能够发现 domain 模式启动时会启动后,有三个进程(相应三个JVM)执行。本文主要研究 domain 模式下是怎样启动多个 JVM 的。

另外,`jboss-modules.jar` 是 JBoss 底层类载入机制,用于类载入和启动一个 JVM。

从启动脚本開始

domain.sh 脚本中例如以下信息:

      eval \"$JAVA\" -D\"[Process Controller]\" $PROCESS_CONTROLLER_JAVA_OPTS \
\"-Dorg.jboss.boot.log.file=$JBOSS_LOG_DIR/process-controller.log\" \
\"-Dlogging.configuration=file:$JBOSS_CONFIG_DIR/logging.properties\" \
-jar \"$JBOSS_HOME/jboss-modules.jar\" \
-mp \"${JBOSS_MODULEPATH}\" \
org.jboss.as.process-controller \
-jboss-home \"$JBOSS_HOME\" \
-jvm \"$JAVA_FROM_JVM\" \
-mp \"${JBOSS_MODULEPATH}\" \
-- \
\"-Dorg.jboss.boot.log.file=$JBOSS_LOG_DIR/host-controller.log\" \
\"-Dlogging.configuration=file:$JBOSS_CONFIG_DIR/logging.properties\" \
$HOST_CONTROLLER_JAVA_OPTS \
-- \
-default-jvm \"$JAVA_FROM_JVM\" \
'"$@"'
JBOSS_STATUS=$?

基于 JBoss Module 类载入机制,我们查看 org.jboss.as.process-controller,在 `module.xml` 的描写叙述中启动 Main 方法例如以下:

<module xmlns="urn:jboss:module:1.1" name="org.jboss.as.process-controller">
<properties>
<property name="jboss.api" value="private"/>
</properties> <main-class name="org.jboss.as.process.Main"/>

所以我们能够从 `org.jboss.as.process.Main` 类開始,JBoss 是全然开源的。这样非常easy開始调试代码。通过例如以下步骤能够開始调试启动代码:

  • 在 pom.xml 中加入例如以下依赖

                <dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-process-controller</artifactId>
<version>7.2.0.Final-redhat-8</version>
</dependency>

  • 编辑 domain.conf,加入例如以下配置

PROCESS_CONTROLLER_JAVA_OPTS="$PROCESS_CONTROLLER_JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=8788,server=y,suspend=y"
HOST_CONTROLLER_JAVA_OPTS="$HOST_CONTROLLER_JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=y"

  • 以 domain 模式启动 JBoss。在 `org.jboss.as.process.Main` 的 main 方法中加入断点。開始代码调试,例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva3lsaW5zb29uZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

对比之前的启动脚本。main 方法传入的參数例如以下:

-jboss-home, /home/kylin/work/eap/jboss-eap-6.1,
-jvm, /usr/java/jdk1.7.0_21/bin/java,
-mp, /home/kylin/work/eap/jboss-eap-6.1/modules,
--,
-Dorg.jboss.boot.log.file=/home/kylin/work/eap/jboss-eap-6.1/domain/log/host-controller.log,
-Dlogging.configuration=file:/home/kylin/work/eap/jboss-eap-6.1/domain/configuration/logging.properties,
-server, -Xms63m, -Xmx512m, -XX:MaxPermSize=256m, -Djava.net.preferIPv4Stack=true, -Djboss.modules.system.pkgs=org.jboss.byteman,
-Djava.awt.headless=true, -agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=y,
--,
-default-jvm, /usr/java/jdk1.7.0_21/bin/java

domain 模式启动

下图描写叙述 domain 模式启动的过程:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva3lsaW5zb29uZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

依据上图描写叙述,我们将 domain 模式启动描写叙述为以下步骤:

  • 通过启动脚本 `domain.sh` 启动 *Process Controller* JVM,*Process Controller* 启动后监听于端口 0。该段口等待 Host Controller JVM 连接
  • Process Controller 启动 Host Controller。我们随后具体介绍 Process Controller 怎样启动 Host Controller, Host Controller 启动后。首先解析 `host.xml` 文件。获取要启动 Server 信息。并与 Process Controller 建立 TCP 连接,将启动 Server 的信息发送给 Process Controller
  • Process Controller 依据 Host Controller 发送的 Server 信息,启动相关的 Server

如上图。我们能够看到三个 JVM 启动的 Main 方法分别位于三个不同的 module 中: `org.jboss.as.process-controller` (相应的 Main 方法为 `org.jboss.as.process.Main`), `org.jboss.as.host-controller ` (相应的 Main 方法为 `org.jboss.as.host.controller.Main`), `org.jboss.as.server` (相应的 Main 方法为 `org.jboss.as.server.DomainServerMain`)。

Process Controller 怎样启动 Host Controller

Process Controller 和 Host Controller 属于不同的 JVM。Process Controller 启动 Host Controller 是在一个 JVM 中启动还有一个 JVM,启动代码位于 `org.jboss.as.process.ManagedProcess` 例如以下图所看到的:

我们能够通过例如以下代码模拟:

        public static void main(String[] args) throws IOException {

                 List<String> command = new ArrayList<String>();
command.add("/usr/java/jdk1.7.0_21/bin/java");
command.add("-jar");
command.add("/home/kylin/work/eap/jboss-eap-6.1/jboss-modules.jar");
command.add("-version");
ProcessBuilder builder = new ProcessBuilder(command);
builder.directory(new File("/home/kylin/tmp"));
Process process = builder.start();
final InputStream stdout = process.getInputStream();
Thread stdoutThread = new Thread(new ReadTask(stdout, System.out));
stdoutThread.start();
}

点击查看完整代码:org/wildfly/domain/test/PCStartHC.java

执行如上代码输出JBoss EAP 6.1 所使用的 JBoss Module 的版本:

[Host Controller] JBoss Modules version 1.2.0.Final-redhat-1

而上面调试过程中 ProcessBuilder 传入的參数例如以下:

/usr/java/jdk1.7.0_21/bin/java, -D[Host Controller],
-Dorg.jboss.boot.log.file=/home/kylin/work/eap/jboss-eap-6.1/domain/log/host-controller.log,
-Dlogging.configuration=file:/home/kylin/work/eap/jboss-eap-6.1/domain/configuration/logging.properties,
-server, -Xms63m, -Xmx512m, -XX:MaxPermSize=256m, -Djava.net.preferIPv4Stack=true, -Djboss.modules.system.pkgs=org.jboss.byteman,
-Djava.awt.headless=true, -agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=y,
-jar, /home/kylin/work/eap/jboss-eap-6.1/jboss-modules.jar,
-mp, /home/kylin/work/eap/jboss-eap-6.1/modules,
-jaxpmodule, javax.xml.jaxp-provider, org.jboss.as.host-controller, -mp, /home/kylin/work/eap/jboss-eap-6.1/modules,
--pc-address, 127.0.0.1,
--pc-port, 50396,
-default-jvm, /usr/java/jdk1.7.0_21/bin/java,
-Djboss.home.dir=/home/kylin/work/eap/jboss-eap-6.1

如上參数被分为两个部分,上面部分用来启动 Host Controller。以下部分作为 Main 方法參数。传递给 org.jboss.as.host-controller 模块定义的 main-class 中,>查看 main-class 定义例如以下:

<module xmlns="urn:jboss:module:1.1" name="org.jboss.as.host-controller">
<properties>
<property name="jboss.api" value="private"/>
</properties> <main-class name="org.jboss.as.host.controller.Main"/> <resources>
<resource-root path="jboss-as-host-controller-7.2.0.Final-redhat-8.jar"/>

如上,我们能够在 `org.jboss.as.host.controller.Main` 中设定断点,继续调试 Host Controller 启动,例如以下

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva3lsaW5zb29uZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

`org.jboss.as.host.controller.Main` 中传入的參数例如以下:

-mp, /home/kylin/work/eap/jboss-eap-6.1/modules,
--pc-address, 127.0.0.1,
--pc-port, 45210,
-default-jvm, /usr/java/jdk1.7.0_21/bin/java,
-Djboss.home.dir=/home/kylin/work/eap/jboss-eap-6.1

注意,如前面分析,这些參数是从 Process Controller 传递过来的,且通过代码调试显示这些參数与之前分析的同样。

Process Controller 启动 Server

Process Controller 启动 Server 过程全然相似,仅仅是要启动的 Server 信息是通过 Host Controller传递过来的,传递过来的 ProcessBuilder 传入的參数例如以下:

/usr/java/jdk1.7.0_21/bin/java, -D[Server:server-one],
-XX:PermSize=256m, -XX:MaxPermSize=256m, -Xms1303m, -Xmx1303m, -server, -D[Host Controller]=true,
-Djava.awt.headless=true, -Djboss.modules.system.pkgs=org.jboss.byteman, -Djboss.home.dir=/home/kylin/work/eap/jboss-eap-6.1,
-Djava.net.preferIPv4Stack=true, -Djboss.server.log.dir=/home/kylin/work/eap/jboss-eap-6.1/domain/servers/server-one/log,
-Djboss.server.temp.dir=/home/kylin/work/eap/jboss-eap-6.1/domain/servers/server-one/tmp,
-Djboss.server.data.dir=/home/kylin/work/eap/jboss-eap-6.1/domain/servers/server-one/data,
-Dlogging.configuration=file:/home/kylin/work/eap/jboss-eap-6.1/domain/servers/server-one/data/logging.properties,
-jar, /home/kylin/work/eap/jboss-eap-6.1/jboss-modules.jar,
-mp, /home/kylin/work/eap/jboss-eap-6.1/modules, -jaxpmodule, javax.xml.jaxp-provider, org.jboss.as.server

通过 `org.jboss.as.server` 我们能够找到 Server JVM 启动的 Main 方法为 `org.jboss.as.server.DomainServerMain`。

怎样理解 PC。HC,Server

PC 是指 Process Controller。HC 是指 Host Controller(与 HC 相相应的是 Domain Controller,简称 DC)。Server 指的是 JBoss 服务器。

从功能层面来说,PC 用来启动和停止 HC 和 Server,且PC 启动停止 Server 首先须要得到 HC 发来的指令。domain 模式启动完毕后会启动例如以下线程用来停止 HC 和 Servers:

"reaper for Host Controller" prio=10 tid=0x7fc3b000 nid=0x770f in Object.wait() [0x803ab000]
"reaper for Server:server-one" prio=10 tid=0x8320b400 nid=0x7750 in Object.wait() [0x7fdfe000]

PC 启动 HC 与 Server 是在一个 JVM 中启动还有一个 JVM,这样 HC 与 Server 中 System.out 和 System.err 流须要使用 PC 中的相应流。所以 PC 的还有一个左右是输>出 PC 和 Server 中输出流打印输出的信息。domain 模式启动完毕后会启动例如以下线程用来完毕此任务:

"stdout for Host Controller" prio=10 tid=0x7fc3a400 nid=0x770e runnable [0x803fc000]
"stderr for Host Controller" prio=10 tid=0x7fc36000 nid=0x770d runnable [0x8087d000]
"stdout for Server:server-one" prio=10 tid=0x83209c00 nid=0x774f runnable [0x7ff5c000]
"stderr for Server:server-one" prio=10 tid=0x83208400 nid=0x774e runnable [0x7ffad000]

HC 用来管理 Server,Domain 模式的设计的一个目的就是在一台物理服务器上通过端口偏移执行多个 Server,HC 设计用来管理这些 Server。Domain 模式的设计的还有一
个目的是多个物理机器上的多个 Server 能够被统一管理,HC 也能够管理多个物理机器上的多个机器,这样的情况下我们称 HC 为 DC。关于怎样配置 DC 不属于此处讨论>的范畴。

Server 是指 JBoss 服务器平台,为 JEE 应用提供容器。

关闭 Server

本部分演示通过 OS 信号关闭 Server 时 PC 和 HC 相关的 Action。

我们通过例如以下步骤演示:

  • 以 domain 模式启动JBoss
  • 使用 `kill -9 PID` 关闭 Server

观察日志。我们看到例如以下日志输出:

21:39:08,800 INFO  [org.jboss.as.process.Server:server-one.status] (reaper for Server:server-one) JBAS012010: Process 'Server:server-one' finished with an exit status of 137
[Host Controller] 21:39:08,801 INFO [org.jboss.as.host.controller] (ProcessControllerConnection-thread - 2) JBAS010926: Unregistering server server-one
[Host Controller] 21:39:08,806 INFO [org.jboss.as.host.controller] (Remoting "localhost.localdomain:MANAGEMENT" read-1) JBAS010926: Unregistering server server-one

PC 收到关闭 Server 的信息,HC Unregistering Server,例如以下为 `reaper for Server:server-one` 线程的代码:

        public void run() {
final Process process;
synchronized (lock) {
process = ManagedProcess.this.process;
}
int exitCode;
for (;;) try {
exitCode = process.waitFor();
log.processFinished(processName, Integer.valueOf(exitCode));
break;
} catch (InterruptedException e) {
// ignore
}
boolean respawn = false;
boolean slowRespawn = false;
boolean unlimitedRespawn = false;
int respawnCount = 0;
synchronized (lock) { final long endTime = System.currentTimeMillis();
processController.processStopped(processName, endTime - startTime);

分析代码。 `reaper for Server:server-one` 线程堵塞于 exitCode = process.waitFor() 行代码,等待关闭信号,且接收到关闭信号后首先日志输出。processController.processStopped(processName, endTime - startTime) 行通知 HC Unregistering Server。

深入理解 JBoss 7/WildFly Domain 模式启动过程的更多相关文章

  1. 深入理解 JBoss 7/WildFly Standalone 模式启动过程

    概述 JBoss 7/WildFly Standalone 模式启动过程大致例如以下: 启动脚本 standalone.sh 启动 JBoss Modules,JBoss Modules 启动 JBo ...

  2. JBoss 7/WildFly Domain 模式怎样配置 Server 启动的 JVM 參数

    本文演示JBoss 7/WildFly Domain 模式怎样配置 Server 启动的 JVM 參数: 例如以下编辑Domain 模式配置文件 domain/configuration/domain ...

  3. PowerPC-MPC56xx Flash模式启动过程

    https://mp.weixin.qq.com/s/SpBOfzJJ1OizYP-rsLJVqQ   Flash启动模式为最常用模式. 一般情况下,芯片上电之后,从flash起始位置读取第一条指令的 ...

  4. jboss eap 6.3 域(Domain)模式配置

    jboss提供了二种运行模式:standalone(独立运行模式).domain(域模式),日常开发中,使用standalone模式足已:但生产部署时,一个app,往往是部署在jboss集群环境中的, ...

  5. JBoss AS7(Application Server 7)的Standalone模式和Domain模式

    JBoss AS7(Application Server 7)支持两种引导模式:standalone和domain(域). Standalone模式对于很多应用,并不需要domain管理能力,JBos ...

  6. 个人从源码理解angular项目在JIT模式下的启动过程

    通常一个angular项目会有一个个模块(Module)来管理各自的业务,并且必须有一个根模块(AppModule)作为应用的入口模块,整个应用都围绕AppModule展开.可以这么说,AppModu ...

  7. JBoss 系列四十八:JBoss 7/WildFly 使用TCP构建集群

    我知道JBoss 集群Default 的设定就是UDP(JGroups),但在实际环境中的网络环境时常不允许UDP,在这种情况下,我们就需要使用TCP. JBoss 7/WildFly 中负责集群的主 ...

  8. 理解javascript中的策略模式

    理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 使用策略模式的优点如下: 优点:1. 策略模式利用组合,委托等技术和思想,有效 ...

  9. JBoss 7 配置成windows启动服务

    将Jboss7 server 配置成一个windows启动服务的两个文件,部署步骤如下: 1.    先检查是否配置java_home和jboss_home的环境变量,如没配置上先配置,如我的是JBO ...

随机推荐

  1. Jmeter接口测试---get和post及解决乱码问题

    Jmeter接口测试---get请求 1.创建一个线程组 测试计划---添加---Threads ---线程组 2.添加http请求,步骤如下图所示: 3.添加带有参数的get请求,如下图展示内容: ...

  2. React Native组件的结构和生命周期

    React Native组件的结构和生命周期 一.组件的结构 1.导入引用 可以理解为C++编程中的头文件. 导入引用包括导入react native定义的组件.API,以及自定义的组件. 1.1 导 ...

  3. 主库binlog(master-log)与从库relay-log的关系

    主库binlog: # at # :: server id end_log_pos CRC32 COMMIT/*!*/; # at # :: server id end_log_pos CRC32 e ...

  4. STM32的串口DMA收发以及双缓冲区的实现

    在使用STM32的UART的DMA功能总结如下: 首先上代码,这里采用STM32 的USART1作为Demo,RX的DMA为DMA1_Channel5,TX的DMA为DMA1_Channel4.初始化 ...

  5. @ControllerAdvice全局异常拦截

    @ControllerAdvice 拦截异常并统一处理 在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder ...

  6. 02Microsoft SQL Server 安装,卸载,系统服务,系统组件及系统数据库

    Microsoft SQL Server 安装,卸载,系统服务,系统组件及系统数据库 1. Microsoft SQL Server 安装 通过单击下拉框,选择浏览,然后在Active Directo ...

  7. Mkdocs在html网页上看markdown

    目录 Mkdocs在html网页上看markdown 1. 本文目的 2. Mkdocs介绍 3. DEMO的演示 3.1 配置需求 3.2 安装mkdocs 3.3 新建工程 3.4 启动服务器 3 ...

  8. 低版本ie兼容问题的解决方案

    CSS hack \9    所有的IE10及之前 *     IE7以及IE7以下版本的 _     IE6以及IE6以下版本的      !important  提升样式优先级权重 1.ie6,7 ...

  9. STL源码分析之第二级配置器

    前言 第一级是直接调用malloc分配空间, 调用free释放空间, 第二级三就是建立一个内存池, 小于128字节的申请都直接在内存池申请, 不直接调用malloc和free. 本节分析第二级空间配置 ...

  10. LOJ #6009 「网络流 24 题」软件补丁

    题面 某公司发现其研制的一个软件中有 $ n $ 个错误,随即为该软件发放了一批共 $ m $ 个补丁程序.每一个补丁程序都有其特定的适用环境,某个补丁只有在软件中包含某些错误而同时又不包含另一些错误 ...