为 OTN 撰稿
为 Oracle 技术网撰写技术文章,获得报酬的同时可提升技术技能。
了解更多信息
密切关注
OTN 架构师社区
OTN ArchBeat 博客 Facebook Twitter YouTube 随身播图标

使用 Oracle WebLogic 时如何启动和停止 Java EE 环境

作者:René van Wijk Oracle ACE 总监

简化 Java EE 环境的生命周期管理

2014 年 2 月

下载
download-icon13-1Oracle WebLogic

搭建 Java EE 环境时,我们需要一个应用服务器(如 Oracle WebLogic Server),这样可以通过配置跨多台计算机的服务器集群,轻松搭建高可用性环境。在这种环境中,我们还必须考虑生命周期管理:如何启动和停止所有受管服务器?如何停止必须停机维护的计算机上的受管服务器?管理服务器不可用时该怎么办?如何从容恢复崩溃的计算机?

本文将对研究这些问题,并使用 WebLogic Scripting Tool (WLST) 和 Linux Bash 开发可以简化复杂 Java EE 环境生命周期管理的脚本。首先,我们将看看 WebLogic 配置提供的基本脚本,了解如何启动 WebLogic Server 以及如何设置 Java 虚拟机 (JVM) 参数。接下来,我们将介绍 Node Manager 的作用以及如何启动和停止管理服务器。然后,我们将讨论如何停止和启动受管服务器(如果管理服务器不可用或计算机需要停机维护)以及设置崩溃恢复。最后将总结最佳实践。

要事第一

下面是 WebLogic Server 环境中的各种组件:

  • 域:WebLogic Server 管理域是逻辑上相关的一组 WebLogic Server 资源。域包括一个被称作管理服务器的特殊 WebLogic Server 实例,用于集中配置和管理域中的所有资源。通常,我们会配置一个域,包括被称作受管服务器的其他 WebLogic Server 实例。我们将 Web 应用程序、Enterprise JavaBeans (EJB)、Web 服务和其他资源部署到受管服务器上,管理服务器仅用于配置和管理目的。
  • 管理服务器:管理服务器是用于配置整个域的中央控制实体。它维护域的配置文档,并将配置文档中的更改分发到受管服务器;它还充当中枢,用于监视域中的所有资源。
  • 受管服务器:受管服务器承载业务应用程序、应用程序组件、Web 服务及其关联资源。为了优化性能,受管服务器维护域配置文档的一个只读副本。受管服务器启动时,会连接到域的管理服务器,使其配置文档与管理服务器维护的文档同步。

[有关更多信息,请参见:了解 Oracle WebLogic Server:WebLogic Server 域]

除了管理服务器和受管服务器,域还包含受管服务器和部署的应用程序所需的资源和服务。受管服务器可以使用以下资源:

  • 机器定义:机器定义识别一个特定的物理硬件,用于将计算机与其所托管的受管服务器相关联。此信息供节点管理器在重新启动故障的受管服务器时使用,也供集群受管服务器在选择存储复制的会话数据的最佳位置时使用。

Node Manager 是一个 WebLogic Server 实用程序,可用于从远程位置启动、关闭以及重新启动管理服务器和受管服务器实例。此处记载了有关 Node Manager 在 WebLogic 环境中的工作方式的详细信息。

在以下展示的 WLST 脚本中,我们将使用 Node Manager 管理 WebLogic Server 生命周期。我们可以使用 WLST 连接到正在运行的管理服务器,管理活动的 WebLogic 域的配置,或者查看有关域中资源的性能数据。WLST Online 是一个 Java 管理扩展 (JMX) 客户端。它与服务器的内存中受管 bean(MBean,为底层资源提供管理界面的 Java 对象)集合交互。可以根据 MBean 是监视还是配置服务器和资源,将所有 WebLogic Server MBean 组织成以下通用类型之一:

  • 运行时 MBean:包含有关服务器及其资源的运行时状态的信息。它们通常只包含服务器或资源的当前状态,并不持久保存此数据。关闭服务器实例时,将销毁来自运行时 MBean 的所有运行时统计信息和指标。
  • 配置 MBean:包含有关服务器和资源配置的信息。它们代表域的 XML 配置文档中存储的信息。

特别是,为了控制 WebLogic Server 生命周期,我们将使用 ServerLifeCycleRuntimeMBean(提供将服务器从一种状态转换到另一种状态的方法)和 ServerRuntimeMBean(提供用于检索有关服务器实例的运行时信息和将服务器从一种状态转换到另一种状态的方法)。使用这些 MBean,我们可以创建所有环境均可以使用的通用脚本。此处记载了有关 WLST(和 Node Manager)如何管理服务器生命周期的详细信息。

继 WLST 之后,WebLogic Server 还提供了一个管理控制台,部署在管理服务器上。管理控制台提供了一个与 WebLogic Server MBean 交互的图形界面,在此界面上可以:

对 WebLogic Server 生命周期的工作方式有了基本了解之后,我们将看看现成脚本如何设置实际创建 WebLogic 运行时 — 换句话说,启动(或停止)拥有主类 weblogic.Server 的 JVM — 所需的参数。为了运行此类,我们需要告知 JVM 加载哪些类 (CLASSPATH) 和使用哪些原生库 (PATH)。因为这些变量由现成脚本设置,(通常)无需在此级别进行更改。不过,我们通常会更改 JVM 参数(例如内存和垃圾收集方案)。接下来,我们继续设置 Node Manager,并看看如何创建 Node Manager 服务。之后,我们将展示用于管理服务器的脚本,然后是用于受管服务器的脚本。

现成脚本

已经安装了 WebLogic 并配置了 WebLogic 域后,我们将得到以下目录结构:

${DOMAIN_HOME}
     /bin
          setDomainEnv.sh (sets some java options and memory 
parameters, calls ${WEBLOGIC_HOME}/common/bin/commEnv.sh and 
${DOMAIN_HOME}/bin/setUserOverrides.sh)
          setUserOverrides.sh
          startManagedWebLogic.sh
          startWebLogic.sh (calls setDomainEnv.sh)
     startWebLogic.sh (calls /bin/startWebLogic.sh)
${WEBLOGIC_HOME}
     /common/bin
          commEnv.sh (calls ${FUSION_MIDDLEWARE_HOME}/common/bin/commEnv.sh)
${FUSION_MIDDLEWARE_HOME}
     /common/bin
          commEnv.sh (sets among others the ${LD_LIBRARY_PATH} and 
${CLASSPATH} variables that are used in setDomainEnv.sh)

要启动管理服务器,我们运行 startWebLogic.sh 脚本,它将使用以下代码行启动服务器:

${JAVA_HOME}/bin/java ${JAVA_VM} ${MEM_ARGS} -
Dweblogic.Name=${SERVER_NAME} -
Djava.security.policy=${WLS_POLICY_FILE} ${JAVA_OPTIONS} 
${PROXY_SETTINGS} ${SERVER_CLASS}

查看脚本时,我们看到 setDomainEnv.sh 脚本中已经设置了内存参数。我们可以在 setUserOverrides.sh 文件中提供更改。可以使用 ${USER_MEM_ARGS} 变量覆盖内存参数 — 例如:

#!/bin/sh

ADMIN_SERVER_MEM_ARGS="-Xms'${ADMIN_SERVER_HEAP_SIZE}' -
Xmx'${ADMIN_SERVER_HEAP_SIZE}' -
XX:PermSize='${ADMIN_SERVER_PERM_SIZE}' -
XX:MaxPermSize='${ADMIN_SERVER_PERM_SIZE}'"
SERVER_MEM_ARGS="-Xms'${MANAGED_SERVER_HEAP_SIZE}' -
Xmx'${MANAGED_SERVER_HEAP_SIZE}' -
XX:PermSize='${MANAGED_SERVER_PERM_SIZE}' -
XX:MaxPermSize='${MANAGED_SERVER_PERM_SIZE}'"
COHERENCE_SERVER_MEM_ARGS="-Xms'${COHERENCE_SERVER_HEAP_SIZE}' -
Xmx'${COHERENCE_SERVER_HEAP_SIZE}' -
XX:PermSize='${COHERENCE_SERVER_PERM_SIZE}' -
XX:MaxPermSize='${COHERENCE_SERVER_PERM_SIZE}'"
MONITORING_ARGS="-XX:+UnlockCommercialFeatures -
XX:+FlightRecorder"
COHERENCE_MONITORING_ARGS="-Dtangosol.coherence.management=all -
Dtangosol.coherence.management.remote=true"
GARBAGE_COLLECTOR_ARGS="-XX:NewRatio=3 -XX:SurvivorRatio=128 -
XX:MaxTenuringThreshold=0 -XX:+UseParallelGC -XX:MaxGCPauseMillis=200 -
XX:GCTimeRatio=19 -XX:+UseParallelOldGC 
-XX:+UseTLAB"
LARGE_PAGES_ARGS="-XX:LargePageSizeInBytes=2048k -XX:+UseLargePages"

if [ "${ADMIN_URL}" = "" ] ; then
     USER_MEM_ARGS="${ADMIN_SERVER_MEM_ARGS} ${GARBAGE_COLLECTOR_ARGS}"
else
     case ${SERVER_NAME} in
          server_*)
               USER_MEM_ARGS="${SERVER_MEM_ARGS} ${GARBAGE_COLLECTOR_ARGS} 
               ${MONITORING_ARGS}"
          ;;
          coherence_server_1)
               USER_MEM_ARGS="${COHERENCE_SERVER_MEM_ARGS} 
${GARBAGE_COLLECTOR_ARGS} ${COHERENCE_MONITORING_ARGS}"
          ;;
          coherence_server_*)
               USER_MEM_ARGS="${COHERENCE_SERVER_MEM_ARGS} 
${GARBAGE_COLLECTOR_ARGS}"
          ;;
     esac
fi
export USER_MEM_ARGS

#if [ "${WEBLOGIC_EXTENSION_DIRS}" != "" ] ; then
#    WEBLOGIC_EXTENSION_DIRS="${WEBLOGIC_EXTENSION_DIRS}
${CLASSPATHSEP}${DOMAIN_HOME}/lib"
#else
#    WEBLOGIC_EXTENSION_DIRS="${DOMAIN_HOME}/lib"
#fi
#export WEBLOGIC_EXTENSION_DIRS'

如上所述,要启动管理服务器,可以使用 ${DOMAIN_HOME}/startWebLogic.sh。要启动受管服务器,可以使用 ${DOMAIN_HOME}/bin startManagedWebLogic.sh ${MANAGED_SERVER_NAME} ${ADMIN_URL}(注,${ADMIN_URL} 变量已在脚本中设置)。如果在管理服务器不可用的情况下启动受管服务器,将在日志中看到以下警告:

[weblogic@machine1 bin]$ ./startManagedWebLogic.sh coherence_server_1
...
starting weblogic with Java version:
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)
Starting WLS with line:
/u01/app/oracle/weblogic12.1.2/jdk1.7.0_25/bin/java -server   -
Xms512m -Xmx512m -XX:PermSize=256m -XX:MaxPermSize=256m -
XX:NewRatio=3 -XX:SurvivorRatio=128 -XX:MaxTenuringThreshold=0 -
XX:+UseParallelGC -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -
XX:+UseParallelOldGC -XX:+UseTLAB 
-Dtangosol.coherence.management=all 
-Dtangosol.coherence.management.remote=true 
-Dweblogic.Name=coherence_server_1 
-Djava.security.policy=/u01/app/oracle/weblogic12.1.2/installation/
wlserver/server/lib/weblogic.policy  
-Dweblogic.ProductionModeEnabled=true 
-Dweblogic.security.SSL.trustedCAKeyStore=/u01/app/oracle/weblogic12.1.2/installation/
wlserver/server/lib/cacerts  -Xverify:none 
-Djava.endorsed.dirs=/u01/app/oracle/weblogic12.1.2/jdk1.7.0_25/jre/lib/endorsed:/
u01/app/oracle/weblogic12.1.2/installation/wlserver/../oracle_common/modules/
endorsed -da 
-Dwls.home=/u01/app/oracle/weblogic12.1.2/installation/wlserver/server
-Dweblogic.home=/u01/app/oracle/weblogic12.1.2/installation/wlserver/server
-Dweblogic.management.server=http://machine1.com:7001  
 weblogic.Server
...
      ...      

在本例中,受管服务器将以受管服务器独立模式运行。

为基于以共识为基础的租赁的单一服务配置迁移策略时,只能通过 Node Manager 启动受管服务器。

Node Manager

Node Manager 概述提供了 Node Manager 的启动脚本:

${DOMAIN_HOME}
     /bin
          startNodeManager.sh (sets ${NODEMGR_HOME} and calls 
${WEBLOGIC_HOME}/server/bin/startNodeManager.sh)
${WEBLOGIC_HOME}
     /server/bin
          startNodeManager.sh (calls calls 
${FUSION_MIDDLEWARE_HOME}/common/bin/commEnv.sh)

这些脚本的核心是下面的启动行:

"${JAVA_HOME}/bin/java" ${JAVA_VM} ${MEM_ARGS} ${JAVA_OPTIONS} -
Djava.security.policy="${WL_HOME}/server/lib/weblogic.policy" -
Dweblogic.nodemanager.JavaHome="${JAVA_HOME}" -
DListenAddress="${LISTEN_ADDRESS}" -
DListenPort="${LISTEN_PORT}" weblogic.NodeManager -v

使用 WebLogic Scripting Tool 时,使用以下语句启动 Node Manager:

import socket;
node_manager_listen_address = socket.gethostname();

print 'CREATE PATHS';
domain_name=os.getenv('DOMAIN_NAME');
java_home=os.getenv('JAVA_HOME');
middleware_home=os.getenv('MIDDLEWARE_HOME');
weblogic_home=os.getenv('WEBLOGIC_HOME');
fusion_middleware_home=os.getenv('FUSION_MIDDLEWARE_HOME');
configuration_home = os.getenv('CONFIGURATION_HOME');

domain_home=configuration_home + '/domains/' + domain_name;
domain_application_home=configuration_home + '/applications/' + domain_name;
node_manager_home=domain_home + '/nodemanager';

print 'STARTING NODE MANAGER';
startNodeManager(verbose='true', 
NodeManagerHome=node_manager_home, 
ListenPort=node_manager_listen_port, 
ListenAddress=node_manager_listen_address);

要运行此脚本,请使用:

#!/bin/sh

SCRIPT=$(readlink -f $0)
SCRIPT_PATH=$(dirname $SCRIPT)

. ${SCRIPT_PATH}/../SetEnvironmentVariables.sh

${WEBLOGIC_HOME}/common/bin/wlst.sh -loadProperties 
${SCRIPT_PATH}/../environment.properties 
${SCRIPT_PATH}/startNodeManager.py

所用环境变量由名为 SetEnvironmentVariables.sh 的脚本设置:

#!/bin/sh

# Name of the domain
DOMAIN_NAME="base_domain"
export DOMAIN_NAME

# Directory where the software to be installed is located
SOFTWARE_DIRECTORY="/u01/software/weblogic/12.1.2"
export SOFTWARE_DIRECTORY

# The scripts create files that are placed in this directory
TEMPORARY_DIRECTORY="${SOFTWARE_DIRECTORY}/files"
export TEMPORARY_DIRECTORY

# Name of JVM file
JVM_FILE_NAME="jdk-7u25-linux-x64.tar.gz"
export JVM_FILE_NAME

# Name of the WebLogic file
WEBLOGIC_FILE_NAME="wls_121200.jar"
export WEBLOGIC_FILE_NAME

# Base directory
BASE_DIRECTORY="/u01/app/oracle"
export BASE_DIRECTORY

# Directory that will used for the installation and configuration
RUNTIME_HOME="${BASE_DIRECTORY}/weblogic12.1.2"
export RUNTIME_HOME

# Directory where the JVM will be installed
JAVA_HOME="${RUNTIME_HOME}/jdk1.7.0_25"
export JAVA_HOME

# Directory that will be used as the middleware home 
(holds software binaries)
MIDDLEWARE_HOME="${RUNTIME_HOME}/installation"
export MIDDLEWARE_HOME

# Depending on the WebLogic version to be installed, 
edit the wlserver_major.minor version
WEBLOGIC_HOME="${MIDDLEWARE_HOME}/wlserver"
export WEBLOGIC_HOME

# Depending on the Coherence version to be installed, 
edit the coherence_major.minor version
COHERENCE_HOME="${MIDDLEWARE_HOME}/coherence"
export COHERENCE_HOME

# Directory where the fusion middleware software will be installed
FUSION_MIDDLEWARE_HOME="${MIDDLEWARE_HOME}/oracle_common"
export FUSION_MIDDLEWARE_HOME

# Location of the Oracle inventory
ORACLE_INVENTORY_HOME="${BASE_DIRECTORY}/oraInventory"
export ORACLE_INVENTORY_HOME

# Group under which the software needs to be installed
ORACLE_INSTALL_GROUP="javainstall"
export ORACLE_INSTALL_GROUP

# Directory where the configuration will be placed
CONFIGURATION_HOME="${RUNTIME_HOME}/configuration"
export CONFIGURATION_HOME

这对应于先前所述的目录结构。使用 WebLogic Scripting Tool 时,通过以下属性文件 (environment.properties) 设置用户名、密码等:

  node_manager_username=nodemanager
  node_manager_password=magic12c
  node_manager_listen_port=5556
  node_manager_mode=plain
  admin_server_name=AdminServer
  admin_username=weblogic
  admin_password=magic12c
  admin_server_listen_port=7001

下面是如何对密码进行加密的例子。如果要在其他环境中使用该脚本,只需更改文件 SetEnvironmentVariables.shenvironment.properties

一般来说,应在计算机启动时启动 Node Manager。本例中,我们需要了解在何处放置系统启动时将调用的自定义命令。Linux 有一个 /etc/rc.d/rc.local 文件,可以在其中放置自定义命令。

我们采用推荐的基于脚本的方式来完成此操作。基于 Unix 的系统指定所谓的运行级别;对于每个运行级别,可以定义启动某个服务的脚本。这些脚本位于 /etc/rc.d/init.d 目录下。可在系统启动时启动服务,或在系统关闭时停止服务。由 /etc/rc.d 目录中的特定目录指定不同运行级别:

  • rc0.d — 系统关闭时执行的脚本
  • rc1.d — 单用户模式脚本
  • rc2.d — 多用户模式脚本
  • rc3.d — 多用户模式和联网的脚本
  • rc4.d — 未使用
  • rc5.d — 与 rc3.d 相同,增加了一些图形元素
  • rc6.d — 系统重新启动时执行的脚本

启动序列如下所示:在 /etc/inittab 文件中,定义启动运行级别,调用脚本 /etc/rc.d/rc.sysinit,然后运行 /etc/rc.d/rcrc 脚本查看 /etc/rc.d/rc<start-runlevel>.d,以 stop 选项执行 K**<script-name> 脚本。之后,使用 start 选项执行 S**<script-name> 脚本。(注意:脚本按数字顺序启动,即 S10network 脚本在 S80sendmail 脚本之前执行。)

要创建 Node Manager“服务”,请使用以下脚本:

#!/bin/sh
#
# chkconfig: - 91 35
#
# description: Node Manager controls the WebLogic Server runtime 
lifecycle
# processname: nodemanager
#

# Source function library.
. /etc/rc.d/init.d/functions

RETVAL=0
SERVICE="nodemanager"
USER="weblogic"
SCRIPTS_LOCATION="/u01/software/weblogic/12.1.2/scripts
/lifecycle"
LOCK_FILE="/var/lock/subsys/${SERVICE}"

start() {
     echo "Starting Node Manager"
     su - ${USER} -c "${SCRIPTS_LOCATION}/NodeManagerStartService.sh" >
/dev/null 2>&1
     RETVAL=$?
     [ $RETVAL -eq 0 ] && success || failure
     echo
     [ $RETVAL -eq 0 ] && touch ${LOCK_FILE}
     return $RETVAL
} 

stop() {
     echo "Stopping Node Manager"
     su - ${USER} -c "${SCRIPTS_LOCATION}/NodeManagerStopService.sh" >
/dev/null 2>&1
     RETVAL=$?
     [ $RETVAL -eq 0 ] && success || failure
     echo
     [ $RETVAL -eq 0 ] && rm -r ${LOCK_FILE}
     return $RETVAL
} 

case "$1" in
     start)
          start
          ;;
     stop)
          stop
          ;;
     restart)
          stop
          start
          ;;
     *)
          echo $"Usage: $0 {start|stop|restart}"
          exit 1
esac 

exit $?

将此脚本放在 /etc/rc.d/init.d 目录中。使用 chkconfig 命令更新系统服务的运行级别信息(例如 chkconfig --add nodemanager and chkconfig nodemanager on)。要测试设置,请关闭系统,然后再重新启动。要检查 Node Manager 是否在运行,请使用 ps -ef|grep javanetstat -anp|grep :5556(假定Node Manager 监听端口 5556)。

还可以考虑将 CrashRecoveryEnabled 属性设置为“true”(允许 Node Manager 在系统崩溃后重新启动服务器),因为默认情况下此属性未启用。系统重启之后,Node Manager 检查 nodemanager.domains 文件中指定的每个受管域,以确定是否有任何服务器实例未彻底关闭。判断的依据是看是否存在任何锁定文件,这种文件在创建 WebLogic Server 进程时由 Node Manager 创建。此锁定文件包含 WebLogic Server 启动脚本的进程标识符。如果存在锁定文件,但进程 ID 未在运行,Node Manager 会尝试自动重新启动服务器。如果进程在运行,Node Manager 会执行额外的检查,访问进程中运行的管理 servlet,以验证与进程 ID 对应的进程是否为 WebLogic Server 实例。要测试进程,请启动所有服务器,然后重新启动主机。服务器重新运行之后,状态文件 (${DOMAIN_HOME}/server/${SERVER_NAME}/data/nodemanager/${SERVER_NAME}.state) 中会包含一个 FORCE_SHUTTING_DOWN 条目。在本例中,对于控制台或 WebLogic Scripting Tool 启动的服务器,服务器会处于不兼容状态。CrashRecoveryEnabled 设置为 true,因此 Node Manager 将检测锁定文件并自动启动服务器;我们可以手动编辑状态文件并将状态设置为 SHUTDOWN,这非常适合在具有多台服务器的环境中运行。

...
<Aug 26, 2013 11:24:08 AM CEST> <INFO> <base_domain> 
<coherence_server_1> 
<The server 'coherence_server_1' is running now.>
<Aug 26, 2013 11:24:15 AM CEST> <INFO> <base_domain> 
<server_machine1.com_9002> 
<The server 'server_machine1.com_9002' is running now.>
<Aug 26, 2013 11:24:16 AM CEST> <INFO> <base_domain> 
<server_machine1.com_9001> 
<The server 'server_machine1.com_9001' is running now.>
# reboot
<Aug 26, 2013 11:30:16 AM CEST> <INFO> <Loading domains file:
 /u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/nodemanager/
nodemanager.domains>
<Aug 26, 2013 11:30:17 AM CEST> <INFO> <Loaded NodeManager 
configuration properties from '/u01/app/oracle/weblogic12.1.2/configuration/domains/
base_domain/nodemanager/nodemanager.properties'>
<Aug 26, 2013 11:30:17 AM CEST> <INFO> 
<WebLogic Server 12.1.2.0.0  Fri Jun 7 15:16:15 PDT 2013 1530982 
WLS_12.1.2.0.0_GENERIC_130607.1100>
...
<Aug 26, 2013 11:30:17 AM CEST> <INFO> <base_domain> 
<AdminServer> 
<Automatically restarting server process as part of crash recovery>
...
<Aug 26, 2013 11:30:18 AM CEST> <INFO> <base_domain> 
<AdminServer> <Starting WebLogic server with command line:
 /u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/bin/
startWebLogic.sh >
...
<Aug 26, 2013 11:31:05 AM CEST> <INFO> <base_domain> 
<AdminServer> <The server 'AdminServer' is running now.>
...
<Aug 26, 2013 11:31:05 AM CEST> <INFO> <base_domain> 
<coherence_server_1> <Automatically restarting server process 
as part of crash recovery>
...
<Aug 26, 2013 11:31:05 AM CEST> <INFO> <base_domain> 
<coherence_server_1> <Starting WebLogic server with command line:
 /u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/bin/
startWebLogic.sh >
...
<Aug 26, 2013 11:31:05 AM CEST> <INFO> <base_domain> 
<server_machine1.com_9002> <Automatically restarting server 
process as part of crash recovery>
...
<Aug 26, 2013 11:31:05 AM CEST> <INFO> <base_domain> 
<server_machine1.com_9002> <Starting WebLogic server with command line:
 /u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/bin/
startWebLogic.sh >
...
<Aug 26, 2013 11:31:05 AM CEST> <INFO> <base_domain> 
<server_machine1.com_9001> <Automatically restarting server 
process as part of crash recovery>
...
<Aug 26, 2013 11:31:05 AM CEST> <INFO> <base_domain> 
<server_machine1.com_9001> <Starting WebLogic server with command line:
 /u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/bin/
startWebLogic.sh >
...
<Aug 26, 2013 11:31:05 AM CEST> <INFO> 
<Plain socket listener started on port 5556, host machine1.com>
<Aug 26, 2013 11:31:26 AM CEST> <INFO> <base_domain> 
<coherence_server_1> 
<The server 'coherence_server_1' is running now.>
<Aug 26, 2013 11:31:30 AM CEST> <INFO> <base_domain> 
<server_machine1.com_9001> 
<The server 'server_machine1.com_9001' is running now.>
<Aug 26, 2013 11:31:36 AM CEST> <INFO> <base_domain> 
<server_machine1.com_9002> 
<The server 'server_machine1.com_9002' is running now.>
...

要停止 Node Manager,我们可以使用:

import socket;
node_manager_listen_address = socket.gethostname();

print 'CREATE PATHS';
domain_name=os.getenv('DOMAIN_NAME');
java_home=os.getenv('JAVA_HOME');
middleware_home=os.getenv('MIDDLEWARE_HOME');
weblogic_home=os.getenv('WEBLOGIC_HOME');
fusion_middleware_home=os.getenv('FUSION_MIDDLEWARE_HOME');
configuration_home = os.getenv('CONFIGURATION_HOME');

domain_home=configuration_home + '/domains/' + domain_name;
domain_application_home=configuration_home + '/applications/' 
+ domain_name;
node_manager_home=domain_home + '/nodemanager';

print 'STOPPING NODE MANAGER';
nmConnect(node_manager_username, node_manager_password, 
node_manager_listen_address, node_manager_listen_port, 
domain_name, domain_home, node_manager_mode);
stopNodeManager();

对于 nmConnect,我们可以选择两种方式提供用户名和密码 — 通过属性(如以上示例),或者使用用户配置和密钥文件。对于后一种情况,必须使用 storeUserConfig。例如:

import socket;
node_manager_listen_address = socket.gethostname();
admin_server_listen_address = node_manager_listen_address;

print 'CREATE PATHS';
domain_name=os.getenv('DOMAIN_NAME');
java_home=os.getenv('JAVA_HOME');
middleware_home=os.getenv('MIDDLEWARE_HOME');
weblogic_home=os.getenv('WEBLOGIC_HOME');
fusion_middleware_home=os.getenv('FUSION_MIDDLEWARE_HOME');
configuration_home = os.getenv('CONFIGURATION_HOME');

domain_home=configuration_home + '/domains/' + domain_name;
domain_application_home=configuration_home + '/applications/' + domain_name;
node_manager_home=configuration_home + '/nodemanagers/' + domain_name;

print 'CONNECT TO NODE MANAGER';
nmConnect(node_manager_username, node_manager_password, node_manager_listen_address, 
node_manager_listen_port, domain_name, domain_home, node_manager_mode);

print 'CREATE NODE MANAGER USER CONFIG FILES';
storeUserConfig(domain_home +'/node_manager_config_file.properties', domain_home + 
'/node_manager_key_file.properties', 'true');

print 'DISCONNECT FROM NODE MANAGER';
nmDisconnect();

print 'CONNECT TO ADMIN SERVER';
admin_server_url = 't3://' + admin_server_listen_address + ':' 
+ admin_server_listen_port;
connect(admin_username, admin_password, admin_server_url);

print 'CREATE ADMIN SERVER USER CONFIG FILES';
storeUserConfig(domain_home +'/admin_server_config_file.properties', 
domain_home + '/admin_server_key_file.properties', 'false');

print 'DISCONNECT FROM THE ADMIN SERVER';
disconnect();

脚本运行时,可以观察到以下输出:

[weblogic@machine1 basicconfiguration]$ ./StoreUserConfigService.sh 

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

CREATE PATHS
CONNECT TO NODE MANAGER
Connecting to Node Manager ...
Successfully Connected to Node Manager.
CREATE NODE MANAGER USER CONFIG FILES
Currently connected to Node Manager to monitor the domain base_domain.
Creating the key file can reduce the security of your system if it is 
not kept in a secured location after it is created. Do you want to create 
the key file? y or ny
The username and password that were used for this WebLogic NodeManager 
connection are stored in /u01/app/oracle/weblogic12.1.2/configuration/domains
/base_domain/node_manager_config_file.properties and 
/u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain
/node_manager_key_file.properties.
DISCONNECT FROM NODE MANAGER
Successfully disconnected from Node Manager.
CONNECT TO ADMIN SERVER
Connecting to t3://machine1.com:7001 with userid weblogic ...
Successfully connected to Admin Server "AdminServer" that belongs to 
domain "base_domain".

Warning: An insecure protocol was used to connect to the 
server. To ensure on-the-wire security, the SSL port or 
Admin port should be used instead.

CREATE ADMIN SERVER USER CONFIG FILES
Creating the key file can reduce the security of your system if it is not 
kept in a secured location after it is created. Do you want to create the 
key file? y or ny
The username and password that were used for this WebLogic Server connection 
are stored in /u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain
/admin_server_config_file.properties and /u01/app/oracle/weblogic12.1.2
/configuration/domains/base_domain
/admin_server_key_file.properties.
DISCONNECT FROM THE ADMIN SERVER
Disconnected from weblogic server: AdminServer

可以这样使用存储的配置文件:

import socket;
node_manager_listen_address = socket.gethostname();

print 'CREATE PATHS';
domain_name=os.getenv('DOMAIN_NAME');
java_home=os.getenv('JAVA_HOME');
middleware_home=os.getenv('MIDDLEWARE_HOME');
weblogic_home=os.getenv('WEBLOGIC_HOME');
fusion_middleware_home=os.getenv('FUSION_MIDDLEWARE_HOME');
configuration_home = os.getenv('CONFIGURATION_HOME');

domain_home=configuration_home + '/domains/' + domain_name;
domain_application_home=configuration_home + '/applications/' + domain_name;
node_manager_home=domain_home + '/nodemanager';

print 'STOPPING NODE MANAGER';
#nmConnect(node_manager_username, node_manager_password, 
node_manager_listen_address, node_manager_listen_port, domain_name, 
domain_home, node_manager_mode);
nmConnect(userConfigFile=domain_home +'/node_manager_config_file.properties', 
userKeyFile=domain_home + '/node_manager_key_file.properties', 
host=node_manager_listen_address, port=node_manager_listen_port, 
domainName=domain_name, domainDir=domain_home, nmType=node_manager_mode);
stopNodeManager();

Node Manager 运行时,我们可以启动管理服务器。

管理服务器

要通过 Node Manager 启动管理服务器,请使用 nmStart。例如:

import socket;
node_manager_listen_address = socket.gethostname();

print 'CREATE PATHS';
domain_name=os.getenv('DOMAIN_NAME');
java_home=os.getenv('JAVA_HOME');
middleware_home=os.getenv('MIDDLEWARE_HOME');
weblogic_home=os.getenv('WEBLOGIC_HOME');
fusion_middleware_home=os.getenv('FUSION_MIDDLEWARE_HOME');
configuration_home = os.getenv('CONFIGURATION_HOME');

domain_home=configuration_home + '/domains/' + domain_name;
domain_application_home=configuration_home + '/applications/' + domain_name;
node_manager_home=domain_home + '/nodemanager';

print 'CONNECT TO NODE MANAGER';
nmConnect(node_manager_username, node_manager_password, node_manager_listen_address, 
node_manager_listen_port, domain_name, domain_home, node_manager_mode);

print 'START ADMIN SERVER';
nmStart(admin_server_name);

print 'DISCONNECT FROM NODE MANAGER';
nmDisconnect();

注: 要想使用 nmStart 启动服务器,boot.properties(在 ${DOMAIN_HOME}/servers/${ADMIN_SERVER_NAME}/security 中)必须存在。要停止管理服务器,我们可以使用:

import socket;
node_manager_listen_address = socket.gethostname();
admin_server_listen_address = node_manager_listen_address;

print 'CREATE PATHS';
domain_name=os.getenv('DOMAIN_NAME');
java_home=os.getenv('JAVA_HOME');
middleware_home=os.getenv('MIDDLEWARE_HOME');
weblogic_home=os.getenv('WEBLOGIC_HOME');
fusion_middleware_home=os.getenv('FUSION_MIDDLEWARE_HOME');
configuration_home = os.getenv('CONFIGURATION_HOME');

domain_home=configuration_home + '/domains/' + domain_name;
domain_application_home=configuration_home + '/applications/' + domain_name;
node_manager_home=domain_home + '/nodemanager';

print 'CONNECT TO ADMIN SERVER';
admin_server_url = 't3://' + admin_server_listen_address + ':' 
+ admin_server_listen_port;
connect(admin_username, admin_password, admin_server_url);

print 'CONNECT TO NODE MANAGER';
nmConnect(node_manager_username, node_manager_password, node_manager_listen_address, 
node_manager_listen_port, domain_name, domain_home, node_manager_mode);

print 'STOPPING ADMIN SERVER';
shutdown(admin_server_name,'Server','true',1000,'true');

print 'DISCONNECT FROM NODE MANAGER';
nmDisconnect();

虽然我们也可以使用 nmKill 而不是 shutdown 来停止管理服务器,但使用 shutdown 命令关闭服务器时,可以更细微地进行控制,如设置一个超时,从容地关闭服务器。

通常,启动 WebLogic Server 实例时,会启动所有服务,包括 Enterprise JavaBeans (EJB)、Java 消息服务 (JMS)、Java EE Connector Architecture (JCA)、集群、部署、管理等等。但 WebLogic Server 提供了一个启动选项 (-DserverType="wlx"),通过从启动名单中排除一部分服务,可以减少运行时的资源占用。这种启动模式可以提高 WebLogic Server 的启动速度,并减少主机上资源的占用空间。WebLogic Server 实例中启动的服务名单由服务器类型启动命令决定,它可以接受服务器类型选项。有两个服务器类型选项:

  • wls — 启动所有服务(默认值)
  • wlx — 启动除以下服务外的所有服务:
    • Enterprise JavaBeans (EJB)
    • Java EE Connector Architecture (JCA)
    • Java 消息服务 (JMS)

如果 WebLogic Server 实例不需要使用这些服务,就可以运行轻型运行时,从而提高性能。

受管服务器

为了停止和启动域中的受管服务器,我们将使用 ServerLifeCycleRuntimeMBean,它提供将服务器从一种状态转换到另一种状态的方法。此类只在管理服务器上实例化,可用于转换受管服务器的状态(不能用于启动管理服务器)。若要用它来启动受管服务器,必须先在每个受管服务器的主机上安装 Node Manager。要启动受管服务器,可以使用:

import socket;

print 'CONNECT TO ADMIN SERVER';
admin_server_listen_address = socket.gethostname();
admin_server_url = 't3://' + admin_server_listen_address + ':' 
+ admin_server_listen_port;
connect(admin_username, admin_password, admin_server_url);

print 'STARTING SERVERS';
domainRuntime();
server_lifecycles = cmo.getServerLifeCycleRuntimes();

for server_lifecycle in server_lifecycles:
     if (server_lifecycle.getState() == 'SHUTDOWN' and server_lifecycle.getName() 
     != admin_server_name):
          print 'START SERVER ' + server_lifecycle.getName();
          task = server_lifecycle.start();
          java.lang.Thread.sleep(1000);
          print task.getStatus() + ', ' + server_lifecycle.getState();
     else:
          print 'SERVER ' + server_lifecycle.getName() + ' is in ' 
+ server_lifecycle.getState() + ' state and will not be started';

print 'DISCONNECT FROM THE ADMIN SERVER';
disconnect();

要停止受管服务器,可以使用:

import socket;

print 'CONNECT TO ADMIN SERVER';
admin_server_listen_address = socket.gethostname();
admin_server_url = 't3://' + admin_server_listen_address + ':' 
+ admin_server_listen_port;
connect(admin_username, admin_password, admin_server_url);

print 'STOPPING SERVERS';
domainRuntime();
server_lifecycles = cmo.getServerLifeCycleRuntimes();

for server_lifecycle in server_lifecycles:
     if (server_lifecycle.getState() == 'RUNNING' and server_lifecycle.getName() 
     != admin_server_name):
          print 'STOP SERVER ' + server_lifecycle.getName();
          task = server_lifecycle.shutdown(1000, java.lang.Boolean('true'));
          java.lang.Thread.sleep(1000);
          print task.getStatus() + ', ' + server_lifecycle.getState();
     else:
          print 'SERVER ' + server_lifecycle.getName() + ' is in ' + 
          server_lifecycle.getState() + ' state and will not be stopped';

print 'DISCONNECT FROM THE ADMIN SERVER';
disconnect();

使用存储的用户配置文件,还可以采用以下方式连接到管理服务器:

connect(userConfigFile=domain_home +'/admin_server_config_file.properties', 
userKeyFile=domain_home + '/admin_server_key_file.properties', 
url=admin_server_url);

以上脚本将启动和停止域中的所有受管服务器。如果只想停止某个主机上的服务器,我们需要了解 WebLogic 实例实际运行在哪个主机上。这种情况下,可以使用 ServerRuntimeMBean,它提供了用于检索有关服务器实例的运行时信息的方法,以及用于将服务器从一种状态转换到另一种状态的方法。使用以下方式在本地停止受管服务器实例:

import socket;
node_manager_listen_address=socket.gethostname();
node_manager_listen_ip_address=socket.gethostbyname(node_manager_listen_address);

print 'CREATE PATHS';
domain_name=os.getenv('DOMAIN_NAME');
java_home=os.getenv('JAVA_HOME');
middleware_home=os.getenv('MIDDLEWARE_HOME');
weblogic_home=os.getenv('WEBLOGIC_HOME');
fusion_middleware_home=os.getenv('FUSION_MIDDLEWARE_HOME');
configuration_home = os.getenv('CONFIGURATION_HOME');

domain_home=configuration_home + '/domains/' + domain_name;
domain_application_home=configuration_home + '/applications/' + domain_name;
node_manager_home=configuration_home + '/nodemanagers/' + domain_name;

print 'CONNECT TO ADMIN SERVER';
command_output = os.popen('find ' + domain_home + ' -name startup.properties');
output = command_output.readline();
command_output.close();
loadProperties(output.rstrip());
admin_server_url = AdminURL.replace('http','t3');
connect(admin_username, admin_password, admin_server_url);

print 'CONNECT TO NODE MANAGER ON ' + node_manager_listen_address + ':' 
+ repr(node_manager_listen_port);
nmConnect(node_manager_username, node_manager_password, node_manager_listen_address, 
node_manager_listen_port, domain_name, domain_home, node_manager_mode);

domainRuntime();
cd('ServerRuntimes');
server_runtimes = ls(returnMap='true');
for server_runtime in server_runtimes:
     cd(server_runtime);
     if (cmo.getName() != admin_server_name):
          host = cmo.getListenAddress().split('/');
          if (node_manager_listen_address == host[0] or node_manager_listen_ip_address 
          == host[1]):
               print 'STOP SERVER ' + cmo.getName();
               shutdown(cmo.getName(),'Server','true',1000,'true');
          else:
               print 'SERVER ' + cmo.getName() + ' runs on a different host and will 
               not be stopped';
     else:
          print 'SERVER ' + cmo.getName() + ' is the Admin Server and will not be 
          stopped';
     cd('..');

print 'DISCONNECT FROM NODE MANAGER ON ' + node_manager_listen_address + ':' 
+ repr(node_manager_listen_port);
nmDisconnect();

print 'DISCONNECT FROM THE ADMIN SERVER';
disconnect();

在此,我们使用首次通过 Node Manager 启动服务器时创建的 startup.properties 文件 (${DOMAIN_HOME}/servers/${SERVER_NAME}/data/nodemanager) 检索管理服务器 URL。startup.properties 中的 AdminURL 属性包含管理服务器的 URL。脚本运行时,可以观察到以下输出:

[weblogic@machine2 lifecycle]$ ./LocalStopService.sh 

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

CREATE PATHS
CONNECT TO ADMIN SERVER
Connecting to t3://192.168.1.155:7001 with userid weblogic ...
Successfully connected to Admin Server "AdminServer" that belongs to domain "base_domain".

Warning: An insecure protocol was used to connect to the 
server. To ensure on-the-wire security, the SSL port or 
Admin port should be used instead.

CONNECT TO NODE MANAGER ON machine2.com:'5556'
Connecting to Node Manager ...
Successfully Connected to Node Manager.
Location changed to domainRuntime tree. This is a read-only tree with DomainMBean as the root. 
For more help, use help('domainRuntime')

dr--   AdminServer
dr--   coherence_server_1
dr--   coherence_server_2
dr--   server_machine1.com_9001
dr--   server_machine1.com_9002
dr--   server_machine2.com_9001
dr--   server_machine2.com_9002

SERVER AdminServer is the Admin Server and will not be stopped
SERVER coherence_server_1 runs on a different host and will not be stopped
STOP SERVER coherence_server_2
Shutting down the server coherence_server_2 with force=true while connected to AdminServer ...

SERVER server_machine1.com_9001 runs on a different host and will not be stopped
SERVER server_machine1.com_9002 runs on a different host and will not be stopped
STOP SERVER server_machine2.com_9001
Shutting down the server server_machine2.com_9001 with force=true while connected to 
AdminServer ...

STOP SERVER server_machine2.com_9002
Shutting down the server server_machine2.com_9002 with force=true while connected to 
AdminServer ...

DISCONNECT FROM NODE MANAGER ON machine2.com:'5556'
Successfully disconnected from Node Manager.
DISCONNECT FROM THE ADMIN SERVER
Disconnected from weblogic server: AdminServer

在以上所示脚本中,我们连接到管理服务器以检索运行时信息。若遇管理服务器不可用,但我们又希望停止和启动受管服务器,则必须分别转而使用 nmKillnmStart。要以独立模式启动受管服务器,可以使用:

nmConnect(node_manager_username, node_manager_password, node_manager_listen_address, 
node_manager_listen_port, domain_name, domain_home, node_manager_mode);
nmStart(managed_server_name);

示例如下:

wls:/offline> nmConnect(node_manager_username, node_manager_password, 
node_manager_listen_address, node_manager_listen_port, domain_name, domain_home, 
node_manager_mode);
Connecting to Node Manager ...
Successfully Connected to Node Manager.

wls:/nm/base_domain> nmStart('coherence_server_2');
Starting server coherence_server_2 ...
Successfully started server coherence_server_2 ...

要使用 nmStart,我们需要获得服务器名称。${DOMAIN_HOME}/servers 包含以服务器名称命名的目录,例如,本例中为:

${DOMAIN_HOME}
     /servers
          /AdminServer
          /coherence_server_1
          /domain_bak
          /server_machine1.com_9001
          /server_machine2.com_9002

使用 File API 获得目录的名称。要将此与 WLST 命令 nmConnectnmStart(或 nmKill)组合,请创建如下脚本:

import socket;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;

print 'CREATE PATHS';
domain_name=os.getenv('DOMAIN_NAME');
java_home=os.getenv('JAVA_HOME');
middleware_home=os.getenv('MIDDLEWARE_HOME');
weblogic_home=os.getenv('WEBLOGIC_HOME');
fusion_middleware_home=os.getenv('FUSION_MIDDLEWARE_HOME');
configuration_home = os.getenv('CONFIGURATION_HOME');

domain_home=configuration_home + '/domains/' + domain_name;
domain_application_home=configuration_home + '/applications/' + domain_name;
node_manager_home=domain_home + '/nodemanager';

print 'OBTAIN SERVER NAMES';
defiles = java.io.File(domain_home + '/servers');
delist = java.util.Arrays.asList(defiles.list());
denames = java.util.ArrayList(delist);

print 'CONNECT TO NODE MANAGER';
node_manager_listen_address = socket.gethostname();
nmConnect(node_manager_username, node_manager_password, node_manager_listen_address, 
node_manager_listen_port, domain_name, domain_home, node_manager_mode);

print 'STARTING SERVERS';
for dename in denames:
     if (dename != admin_server_name and dename != 'domain_bak'):
          nmStart(dename);
          # nmKill(dename);

print 'DISCONNECT FROM NODE MANAGER';
nmDisconnect();

执行此脚本时,可以观察到以下输出:

# nmStart
[weblogic@machine1 lifecycle]$ ./tryout.sh 

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

CREATE PATHS
OBTAIN SERVER NAMES
CONNECT TO NODE MANAGER
Connecting to Node Manager ...
Successfully Connected to Node Manager.
STARTING SERVERS
Starting server server_machine1.com_9002 ...
Successfully started server server_machine1.com_9002 ...
Starting server server_machine1.com_9001 ...
Successfully started server server_machine1.com_9001 ...
Starting server coherence_server_1 ...
Successfully started server coherence_server_1 ...
DISCONNECT FROM NODE MANAGER
Successfully disconnected from Node Manager.

#nmKill
[weblogic@machine1 lifecycle]$ ./tryout.sh 

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

CREATE PATHS
OBTAIN SERVER NAMES
CONNECT TO NODE MANAGER
Connecting to Node Manager ...
Successfully Connected to Node Manager.
STARTING SERVERS
Killing server server_machine1.com_9002 ...
Successfully killed server server_machine1.com_9002
Killing server server_machine1.com_9001 ...
Successfully killed server server_machine1.com_9001
Killing server coherence_server_1 ...
Successfully killed server coherence_server_1
DISCONNECT FROM NODE MANAGER
Successfully disconnected from Node Manager.

注意文档中的注释:“若要使用 nmStart 启动服务器,boot.properties 必须存在。如果您是首次启动服务器或首次使用 Node Manager,必须手动创建该文件,或运行 nmGenBootStartupProps 命令为服务器生成 boot.properties 和 startup.properties 文件。”例如:

wls:/base_domain/serverConfig> nmGenBootStartupProps('coherence_server_1');
Successfully generated boot.properties at
 /u01/software/weblogic/12.1.2/scripts/servers/coherence_server_1/data/nodemanager/
 boot.properties.
Successfully generated startup.properties at
 /u01/software/weblogic/12.1.2/scripts/servers/coherence_server_1/data/nodemanager/
 startup.properties.
在启动 WLST 的目录(因此仍然需要将这些文件复制到 ${DOMAIN_HOME}/servers/${SERVER_NAME}/data/nodemanager 目录)中创建文件。

总结

为 Node Manager 创建一个“服务”是很好的做法,这样就可以在计算机启动时启动 Node Manager。可以考虑将 CrashRecoveryEnabled 设置为“true”,这样计算机重启时就不会有问题了。还可以考虑让 Node Manager 使用明文(而不是 ssl)通信(如果网络实在不安全,也可以使用 ssl 并创建自己的密钥库)。为每个域设置一个 Node Manager,而不是每台计算机。通过 Node Manager 启动管理服务器,并通过管理服务器启动受管服务器。为确保 Node Manager 能够在系统崩溃后正常重启服务器,还必须启用 CrashRecoveryEnabled。这种情况下,计算机的启动序列中只需有 Node Manager 即可。

参考资料

[1] WebLogic Server 文档

关于作者

René van Wijk
Twitter 博客 LinkedIn Facebook Oracle ACE 总监
Oracle ACE 总监 René van Wijk 使用众多技术,包括 Oracle Coherence、Oracle WebLogic、Hibernate、Java 虚拟机、JBoss 和 Spring。他毕业于代尔夫特理工大学,经常通过培训、出版物以及研讨会和各种会议上的演讲活动传授知识和经验。