脚本语言近来受到一些关注。随着Groovy和 Jython的到来,编写与Java合并的脚本比Ant更简单自然。一直以来使用XML来调用Java方法都是被迫的,这主要是因为在标记语言中解释流、条件表达式和自定义代码比较困难(虽然自Ant 1.5之后这一点有了较大的改进)。
为什么用脚本语言呢?是这样的,如果我有完整的Java编程IDE,用Jython或是Groovy看起来就显得有些落伍了。虽然可以用较少行来编码(虽然不是少很多),但是我希望输入的编写能够自动化。我希望编译器在编码时告警,而且我需要分解。这需要Java IDE以外的插件。
但有时候没有完整的IDE配置。想一下要自动敏捷的工作,或者想一下服务器管理员。这些人没有任何像Eclipse之类的东西,而且他们的工作不可能事先完成。不可能为系统管理而编码。这就是像WLST这类工具产生的来由,它们使得世界更美好。
WebLogic 脚本工具(WLST,WebLogic Scripting Tool)是一个帮助编写远程管理和修改服务器安装脚本的Jython模块。它有两个版本:离线,它可以配置尚不存在的服务器实例,以及在线,它需要连接到一个WebLogic服务器。这两个版本都是Beta版而且文档很少,但是它们保证会改进并在将来的某个WebLogic版本中包含。
这里我们将专注于在线版本,因为它的功能比离线版本更为完整。
使服务器配置自动化:
让我们从难以对付的WebLogic服务器配置开始吧!典型的开发团队在几台主机上复制同样的配置,仅仅改变少量参数,如IP、主机名和TCP端口。在相对典型的项目中,必须对每个开发人员的PC、集成测试主机和生产主机,都要执行一遍这个过程。Ant任务对这个问题有很大帮助,但是它还没有准备好处理像定制JMX bean这类的事务。
我们将创建并装载服务器,配置它,然后关机,混合使用Ant和WLST。首先,让我们创建清单1中的服务器。为了简化,我们将在这里使用Ant任务,因为结合使用WLST离线和在线会使事情复杂化。
清单1
build.properties:
server=weblogic
weblogic.server.name=myserver
weblogic.domain.name=mydomain
weblogic.admin.username=weblogic
weblogic.admin.password=weblogic
weblogic.home=C:/bea
weblogic.lib.dir=/weblogic81/server/lib
weblogic.mbeantypes.dir=/mbeantypes
server.project.root.dir=/user_projects/domains/
server.deploy.dir=/applications
我检查了属性,因为在多于一个品牌的应用服务器上部署时,很容易使用错误的build.properties文件(参见清单2)。
清单 2
build.xml:
[...]
<path id="weblogic.classpath">
<fileset dir="">
<include name="weblogic.jar"/>
</fileset>
</path>
<target name="check-properties">
<condition property="wlproperties.ok">
<and>
<isset property="weblogic.server.name"/>
<isset property="weblogic.domain.name"/>
<isset property="weblogic.admin.username"/>
<isset property="weblogic.admin.password"/>
</and>
</condition>
<fail unless="wlproperties.ok">
Weblogic properties are missing. Double check build.properties.
</fail>
<fail>
<condition>
<not><available file="/weblogic.jar"/></ not>
</condition>
Missing file /weblogic.jar
</fail>
</target>
<target name="create-server" depends="check-properties">
<taskdef name="wlserver" classname="weblogic.ant.taskdefs. management.WLServer"
classpathref="weblogic.classpath"/>
<echo>Creating server at </echo>
<delete dir="" includeemptydirs="true" quiet="true"/>
<mkdir dir="" />
<wlserver
dir=""
domainName=""
serverName=""
host=""
port=""
generateConfig="true"
productionModeEnabled="false"
weblogicHome="/weblogic81"
username=""
password=""
action="start"
>
<classpath refid="weblogic.classpath"/>
</wlserver>
我们刚刚删除了整个域目录,创建了一个新的、干净的目录,并让服务器运行,这样,在清单3中,我们可连接并配置它。
清单3
<java classname="weblogic.WLST" fork="true" failOnError="true" dir="scripts/wlst">
<classpath refid="weblogic.classpath"/>
<classpath>
<fileset dir="lib/wlst">
<include name="*.jar"/>
</fileset>
</classpath>
<arg line="createAll.py" />
</java>
<wlserver
host=""
port=""
username=""
password=""
action="shutdown"
/>
</target>
停止服务器是必要的,因为有些设置改变了,如安全验证者,需要正常关机以保存到磁盘。省略这一步将会在Ant脚本结束处突然中止服务器。
注意:WLST任务有分叉,因此,如果WLST在脚本中发现了错误,Ant仍将会显示“成功编译”,从而会使得装载该脚本的人迷惑。
让我们将WLST脚本分成两个部份,这样在以后的管理任务中能尽可能多的重用它。我已经使用了包含在WLST包中的很棒的例子,并且将saveDomain()命令的输出作为起点。saveDomain()生成的脚本不是很完美,但是它能指出工具的可能性(参见清单4)。
清单 4
createAll.py:
execfile("AdminTool.py")
admin.configureServer()
admin.createXaPool()
AdminTool.py:
from javax.management import InstanceNotFoundException
# Python 2.4 will include booleans, but until then this is required
true = 1
false = 0
class AdminTool:
def __init__(self):
loadProperties("administration.properties")
# Connects with a weblogic instance
def connect(self):
connect(username, password, "t3://" + host + ":" + port)
self.myServer = getTarget("/Server/" + serverName)
# Server attributes that cannot be generated via ant
def configureServer(self):
# Activates console DEBUG mode - I really like that
self.myServer.setStdoutSeverityLevel(64)
print "Configured server " + self.myServer.getName()
# Creates a JDBC pool:
def createPool(self, poolName, driverName):
pool = create(poolName, "JDBCConnectionPool")
pool.setDriverName(driverName)
pool.setURL(dbURL)
pool.setPassword(dbPassword)
pool.setProperties(makePropertiesObject("user=" + dbUsername))
pool.setRemoveInfectedConnectionsEnabled(false)
pool.setTestConnectionsOnCreate(true)
pool.setTestTableName("SQL SELECT 1 FROM DUAL")
# setTestFrecuencySeconds is not soported by WLST objects
# so here is a workaround
cd(´/JDBCConnectionPool/´ + poolName)
set(´TestFrequencySeconds´, 300)
cd(´/´)
pool.addTarget(self.myServer)
def createXaPool(self):
self.createPool(MY_POOL_NAME, ´oracle.jdbc.xa.client.? OracleXADataSource´)
# Removes an element if it exists
def removeIfExists(self, name, type):
try:
mbean = home.getAdminMBean(name, type)
home.deleteMBean(mbean)
print ´Removed the ´ + type + ´: ´ + name
except InstanceNotFoundException, e:
print "Cannot remove " + name + ",type=" + type + " because ? it does not exist"
def removeXaPool(self):
self.removeIfExists(MY_POOL_NAME, "JDBCConnectionPool")
# The JDBC Connection Pool name
MY_POOL_NAME=´MyPool´
# the instance we are going to use
admin = AdminTool()
admin.connect()
administration.properties
host=127.0.0.1
port=7001
username=weblogic
password=weblogic
dbURL=jdbc:oracle:thin::1521:DATABASE
dbUsername=foo
dbPassword=bar
LoadProperties任务将administration.properties文件中的所有项转换成Jython变量。我们已经使用了Jython类的第一个方法来管理WebLogic服务器实例。还可以轻易将它扩展到创建和删除DataSources,这是一个JMS环境,甚至还可以扩展到安全领域。
MBean方法
前面我们已经看到的是创建和配置MBeans的一个方法(下一节会解释另一种方法)。不利的一面是必须知道支持的属性和方法,而WLST没有这些文档。我怎么去猜哪个方法可用呢?
噢,我想到的第一个方法是到config.xml文件或是Web控制台去找,并假设属性名称未改变。如果有一个不错的IDE,我们还可以打开Mbean接口类看看那里有些什么(它和Mbean的名称一样,以“Mbean”结束)。这不会显示代码,但是可以查到哪个方法可用。
我喜欢连接到http://e-docs.bea.com/wls/docs81/javadocs/index.html,查看weblogic.management.configuration包的内容。比如,如果我们找到ServerMBean类,就可以看到两个有趣的但是不太为人们所熟悉的方法isJDBCLoggingEnabled()和setJDBCLoggingEnabled()。我们可通过打开wlst交互shell来查看它们,如下所示:
wls:/mydomain/config> server=home.getAdminMBean(´myserver´, ´Server´)
wls:/mydomain/config> server.setJDBCLoggingEnabled(1)
wls:/mydomain/config> server.isJDBCLoggingEnabled()
1
(“home”是一个AdminMbeanHomeImpl类型的变量,可以像对任何其他Mbean一样研究;唯一的问题是因为它是一个内部类,所以没有javadoc可用。)
如果最后三个命令不好理解,不要担心。我们会在下一节介绍Shell。
命令行系统管理
系统管理员也可以通过使用交互式shell来手工管理WebLogic服务器实例。其优点是在试图修改系统配置时,不用事先知道Mbean接口。对这一部分,需要在classpath包含webLogic.jar、jython.jar以及wlst.jar,并启动主类weblogic.WLST,它是交互式控制台。
要记住这是Jython。引号和双引号用于字符串声明;实例化不需要新的运算符(事实上,这是一个语法错误);不需要分号,因为每行用回车结束;而且不必声明变量(la Unix shell脚本)。如果这还不够,请参考Python和WLST的文档。
我们需要开始连接到WebLogic服务器的实例。我们可以选择使用之前编写的AdminTool脚本,或者手工连接:
execfile(´AdminTool.py´)
admin.connect()
或
connect(´weblogic´, ´weblogic´, "t3://localhost:7001)
Connecting to weblogic server instance running at t3://127.0.0.1:7001 as
username weblogic ...
成功连接到属于“mydomain”域的Admin服务器“myserver”是系统输出,而且应采用编码的格式。
现在,我们可以开始好好玩一下了。对于WLST,JMX树可像UNIX文件系统一样进行遍历,在这里JMX Mbeans是目录而其属性是文件。在所有这些过程中要记住Python语法,并要记得WLST仍然不能分辨通配符。这就是为什么我们要省略大多数ls()输出的原因(参见清单5)。
清单5
wls:/mydomain/config> ls()
[...]
drw-JDBCConnectionPools
drw-JDBCDataSourceFactories
drw-JDBCDataSources
drw-JDBCMultiPools
drw-JDBCTxDataSources
[...]
wls:/mydomain/config> cd(´JDBCConnectionPools´)
wls:/mydomain/config/JDBCConnectionPools> ls()
drw-MyPool
wls:/mydomain/config/JDBCConnectionPools> cd(´MyPool´)
wls:/mydomain/config/JDBCConnectionPools/MyPool> ls()
[...]
-rw-TestConnectionsOnCreatetrue
-rw-TestConnectionsOnReleasefalse
-rw-TestConnectionsOnReservefalse
-rw-TestFrequencySeconds300
-rw-TestStatementTimeout-1
-rw-TestTableNameSQL SELECT 1 FROM DUAL
-r--TypeJDBCConnectionPool
-rw-URLjdbc:oracle:thin::1521:DATABASE
[...]
我们还可以对于单个cd(´/JDBCConnectionPools/MyPool´)命令深入到这个地步。WLST永远记得cmo(当前管理对象,Current Managed Object),即与我们正在浏览的当前“文件夹”相关的Mbean。因此,从实际角度来看这些命令是相当的:
wls:/mydomain/config/JDBCConnectionPools/MyPool> cmo
[Caching Stub]Proxy for mydomain:Name=MyPool,Type=JDBCConnectionPool
wls:/mydomain/config/JDBCConnectionPools/MyPool> pwd()
´/JDBCConnectionPools/MyPool´
现在,让我们改变一些随机属性(参见清单6)。记住Python没有布尔属性。服务器可返回真或假(既然它运行Java),但是不能赋这些值。然而,不用担心;如果通过WebLogic控制台查看它,布尔值1得到了服务器的正确解释。
清单 6
wls:/mydomain/config/JDBCConnectionPools/MyPool> set?(´TestFrequencySeconds´, 500)
wls:/mydomain/config/JDBCConnectionPools/MyPool> set(´TestConnectionsOnRelease´, 1)
wls:/mydomain/config/JDBCConnectionPools/MyPool> ls()
-rw-TestConnectionsOnCreatetrue
-rw-TestConnectionsOnRelease1
-rw-TestConnectionsOnReservefalse
-rw-TestFrequencySeconds500
-rw-TestStatementTimeout-1
-rw-TestTableNameSQL SELECT 1 FROM DUAL
-r-- TypeJDBCConnectionPool
-rw-URLjdbc:oracle:?thin::1521:DATABASE
[...]
wls:/mydomain/config/JDBCConnectionPools/MyPool> get(´TestConnectionsOn?Release´)
1
使用前一节关于“使服务器配置自动化”中介绍的相当技术,也可能得到了同样的结果。我发现这个方法对于系统管理员更简单,而第一个方法对于开发人员准备脚本则更简单。这只是适应不同类型的工具集:系统管理员更习惯于Unix Shell,而开发人员对于的Java的“味道”则感觉更为舒服。
管理服务器配置的例子:一个真实例子
需要了解那些烦人的JDBC调用内部是一种常见现象。有时人们真的希望能够看见WebLogic服务器和数据库之间对话,为什么它会见鬼地返回0行,或者轮廓性能,OK。用热插拔功能记录JDBC调用(而不仅是SQL,拜托了,还要记录参数)应该不错。想试一下吗?
首先,让我们下载p6spy JDBC驱动程序。它是一个JDBC包,可以记录任何经过它的东西。要配置它,将p6spy.jar和包含p6spy.properties的目录放到服务器classpath目录下(不要忘了这个目录,否则WebLogic会报告JAR文件不存在)。按照需要调整p6spy.properties。
我们想要到达的目的是创建两个Connection Pool(连接池),一个直接用Oracle JDBC驱动程序而另一个通过p6spy。然后,我们将修改数据源指向p6spy数据源而不重启服务器(如果我们相信Web控制台接口,这个修改无需重启)。
我们将通过执行之前开发出的管理脚本来开始:
wls:/(offline)> execfile(´AdminTool.py´)
Connecting to weblogic server instance running at t3://127.0.0.1:7001 as
username weblogic ...
成功连接到属于“mydomain”域的Admin服务器“myserver”,它也是系统输出并且应正确格式化。
我们现在可以创建连接池了。
wls:/mydomain/config> admin.createPool("P6SPY Connection Pool",
"com.p6spy.engine.spy.P6SpyDriver")
JDBCConnectionPool with name ´P6SPY Connection Pool´
has been created successfully.
在WebLogic控制台我们可看到以下显示(WebLogic日志行将只在将“debug to console”选项启用时才会显示):
<28-feb-2005 20H18´ GMT> <Info> <JDBC> <BEA-001132>
<Initialized statement cache of size "10"
for connection in pool "P6SPY Connection Pool".>
1109621928226|0|1|statement|SELECT 1 FROM DUAL|SELECT 1 FROM DUAL
1109621928242|0|1|statement|SELECT 1 FROM DUAL|SELECT 1 FROM DUAL
这显示连接池初始化以及新连接测试。我们将假设数据源还不存在。如果我们还清楚,应该已经预见到这一点并在AdminTool类创建了方法,但是,我们还是可通过清单7中所列的交互式shell来这么做。
清单 7
wls:/mydomain/config> datasource=create(´MyDS´, ´JDBCTxDataSource´)
JDBCTxDataSource with name ´MyDS´ has been created successfully.
wls:/mydomain/config> datasource.setJNDIName("MyDS")
wls:/mydomain/config> datasource.setPoolName("P6SPY Connection Pool")
wls:/mydomain/config> datasource.setEnableTwoPhaseCommit(true)
wls:/mydomain/config> datasource.addTarget(admin.myServer)
1
我们已经开始将数据源指向P6SPY连接池,因此,可以检查应用程序看看它真的记录了JDBC语句;用测试案例来尝试。现在,有两个方法可以禁止记录。既然在Jython变量中有数据源,我们就可以用“Java”的方式来做。
datasource.setPoolName(MY_POOL_NAME)
或者,采用如清单8所示的“system administrator”方法:
清单8
wls:/mydomain/config> cd (´JDBCTxDataSources´)
wls:/mydomain/config/JDBCTxDataSources> ls()
drw-MyDS
wls:/mydomain/config/JDBCTxDataSources> cd(´MyDS´)
wls:/mydomain/config/JDBCTxDataSources/MyDS> ls()
[...]
-rw-PoolNameMyPool
[...]
wls:/mydomain/config/JDBCTxDataSources/MyDS> set(´PoolName´, MY_POOL_?NAME)
结束语
WLST是一个能够推进应用程序服务器配置和远程维护的杰出工具。它还不支持用通配符查找/定位选项(对于一些并非不常见的情况,如有人需要查找某个配置选项但是想不起它的位置)。但是,当最后与WebLogic 9绑定后,它肯定会非常有用。
参考资料
原文出处
http://wldj.sys-con.com/read/48932.htm
作者简介 |
|
Ignacio Coloma 是InfoInnova的J2EE架构师。过去6年以来,他已经为电子银行、航空运输、电子政府以及消息处理系统开发了许多应用程序。目前,他正在用脚本语言扩展J2EE应用程序。 |
posted on 2005-09-28 18:49
逍遥草 阅读(4197)
评论(0) 编辑 收藏 引用 所属分类:
weblogic+structs