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

为 OTN 撰稿

为 Oracle 技术网撰写技术文章,获得报酬的同时可提升技术技能。

密切关注

OTN 架构师社区

format,pngformat,pngformat,pngformat,pngformat,png

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

作者:René van Wijk format,png

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

2014 年 2 月

搭建 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 服务及其关联资源。为了优化性能,受管服务器维护域配置文档的一个只读副本。受管服务器启动时,会连接到域的管理服务器,使其配置文档与管理服务器维护的文档同步。

除了管理服务器和受管服务器,域还包含受管服务器和部署的应用程序所需的资源和服务。受管服务器可以使用以下资源: 机器定义:机器定义识别一个特定的物理硬件,用于将计算机与其所托管的受管服务器相关联。此信息供节点管理器在重新启动故障的受管服务器时使用,也供集群受管服务器在选择存储复制的会话数据的最佳位置时使用。

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.sh 和 environment.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/rc。rc 脚本查看 /etc/rc.d/rc.d,以 stop 选项执行 K** 脚本。之后,使用 start 选项执行 S** 脚本。(注意:脚本按数字顺序启动,即 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 java 或 netstat -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,这非常适合在具有多台服务器的环境中运行。

...

# reboot

/u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/nodemanager/

nodemanager.domains>

configuration properties from '/u01/app/oracle/weblogic12.1.2/configuration/domains/

base_domain/nodemanager/nodemanager.properties'>

WLS_12.1.2.0.0_GENERIC_130607.1100>

...

...

/u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/bin/

startWebLogic.sh >

...

...

as part of crash recovery>

...

/u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/bin/

startWebLogic.sh >

...

process as part of crash recovery>

...

/u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/bin/

startWebLogic.sh >

...

process as part of crash recovery>

...

/u01/app/oracle/weblogic12.1.2/configuration/domains/base_domain/bin/

startWebLogic.sh >

...

...

要停止 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

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

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 命令 nmConnect 和 nmStart(或 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 即可。

参考资料

关于作者

René van Wijk

sml-twitter.gifblog-icon-box-orange-16.gifsml_linkedin_icon.giffacebook-icon.jpgformat,png

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

您将需要 Skype Credit免费通过 Skype

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书于2011-11月出版,此为该书的前面部分章节电子版 首先,这是一本高水平的书,作为对Oracle 在线文档和其他Java EEWebLogic Server 技术 的入门书的补充,向中高级开发人员、架构师和管理员提供了对关键的Java EE 开发和部署技术 的深入讲解。本书跳过了基础内容,避免重复很容易从其他地方找到的信息,关注其他地方没有 提到的信息和技术。本书由Oracle 公司权威人士和企业级Java EE 应用程序开发专家组成的作者 团队编写,是对其他书籍和参考资料的延伸。 其次,本书描述了思路。不只是简单地罗列出解决问题的各种可选方案,而后让你自己去做 出决策,而且分享了我们的思考过程,给你提供了在应用程序开发和管理过程中能够使用的具体 建议和最佳实践。本书讲解了不同的设计方案、体系结构、构建技术、部署选项以及管理技术, 但是并没有停留在这一步。我们会进而解释每一个可选方案的优点,以及应用这种方案的场合。 我们不仅要让你理解有哪些方法可以完成任务,还要让你理解应该如何完成任务。 最后,本书构建并讲解的主要示例应用程序是一个真实复杂的应用程序,涵盖了很多Java EE 技术的许多特征,以及Oracle WebLogic Server 11g 特有的技术。这个示例应用程序覆盖了JSP、 Spring MVC、EJB 3.0、JPA、JMS 和Web 服务等关键技术,展示了这些技术的应用。正文部分带 你经历这个应用程序设的计、开发和部署过程中每一个决策做出的过程,帮助你在自己的开发工 作中做出类似的决策。 读者对象 本书并不是Java EE 技术和WebLogic Server 环境的入门读物。这是一本高水平的书,对基本 概念的描述很少,因此本书面向的读者是有经验的开发人员和WebLogic Server 管理员,通过阅读 本书他们可以将自己对这些技术的认识提升到更高水平。 主要内容 本书关注于如何通过最新发布的Oracle WebLogic Server 11g 进行Java EE 开发、部署和管理。 书中描述的很多技术、框架、部署技术和管理工具都要求使用这个版本的WebLogic Server 和最新 版本的Java EE 环境以及相关的各种库和框架。本书中构建的主要示例应用程序bigrez.com 要求 使用WebLogic Server 11g。 尽管如此,我们并不赞同“最新的就是最好的”这类技术观点。只要是合理的,我们就会在 示例中选用经过检验且版本可靠的Java EE 框架和库,前提是这些框架和库能够满足我们的需求 并且完成任务。 Oracle WebLogic Server 开发权威指南 VI 下面列出了本书中描述过、比较过并且使用过(或没有使用过)的部分技术和框架: ● EJB 3.0、JPA、OpenJPA、Kodo、TopLink ● Java 6、Spring 2.5 MVC、Jakarta Struts 1.2、JSP 2.0、Tiles 2.0 ● JMS 1.1、SOAP 1.1、JAX-WS 2.1 ● JAAS、SAML 1.1 和2.0、XACML、SSL、TLS 1.0、JSSE ● JMX、SNMP、WLST、WLDF

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值