技术开发 频道

争分夺秒地发布:自动化应用程序推进


用于BEA WebLogic Platform的脚本语言和工具

  正如本文所述,自动化使用脚本工具配置环境。另一种方法是使用虚拟供应,但这种方法不常用。虚拟可以作为脚本的替代方法,能够提供高速供应,将来的文章中我们将讨论这个主题。

  供应的鸟瞰图不仅要包括WebLogic域配置,而且要包括许多其他系统组件的配置,例如:

  • 网络基础架构
  • 防火墙
  • 操作系统补丁
  • 硬件负载平衡器
  • 内容切换
  • 数据库管理
  • 内容管理系统
  • 安全服务集成
  • 后端系统连通性

  我们没有足够的篇幅讨论所有以上组件的端对端安装和配置,因此我故意限制了WebLogic Platform的翻译,将一小部分扩展转入Web服务器和数据库服务器。这些扩展用于说明如何使用类似的技术以及共享相同的供应数据(可用时)来供应其他相关的系统组件。相关组件之间的共享供应数据可以减少许多可能出现的供应错误。

  许多脚本工具都可用于自动化,本文不打算比较这些工具。既然我们一直在讨论WebLogic Platform的供应,我假定使用WLST作为主要的脚本工具。WLST是一个命令行工具,使用Jython脚本语言,Jython本身是Python脚本语言的Java绑定。

  在WebLogic Platform 8.1中,WLST有两个版本。离线版(就叫WLST)用于构建WebLogic域内容,而另一个在线版(称为WLSTOnline)用于监控和更改运行域的配置。在WebLogic Platform 9中,单个WLST工具(叫做WLST)能够以离线和在线模式运行。为了更清楚的说明,我们将讨论用这两者模式使用WLS。如果您使用的是WebLogic Platform 8.1,则意味着您要使用WLST(离线模式)和WLSTOnline (在线模式)。

  在离线模式中,WLST提供与域配置向导等效的脚本。与向导一样,它基于域模版构建一个域,然后使用脚本自定义域。BEA提供许多WLST可以使用的通用模版。WLST可以使用自定义模版构建新域,这些新域类似构建模版的域。在离线模式下,WLST构建并向文件库写入一个域目录结构。供应受控环境时,由于防火墙和其他访问控制的原因,可能无法直接向域服务器所在的机器写入域目录。下文中我们将讨论如何调整访问控制。

  在线模式的WLST类似于WebLogic域控制台Web应用程序的等效脚本形式。除了可以监控其运行状态外,它还能检查和修改活动域的配置。运行在线模式时,WLST不依赖模版,因为它总是对现有的活动域进行操作。在线WLST使用JMX与管理服务器(以及受管服务器,但通常不能是在供应期间)进行通信。这与离线模式有明显的区别,WLST在离线模式只编写目录层次。JMX的访问控制可能限制了JMX接口访问管理服务器的方式,供应脚本必须针对这种约束做出调整。

编写适应性强的脚本

  自动供应最关键的优点在于:您可以使用一个环境的供应脚本作用原型用于其他环境。要实现这一点,编写供应脚本时应该注意使脚本的行为与特定的环境需求相适应。要真正实现适应性强的脚本,您需要一个完善的脚本语言。幸运的是,Jython和Python非常适合这种情况。

  如果您使用 WLST,应该使用Jython语言编写供应脚本。当您启动WLST并执行其脚本时,您实际上运行的是WLST工具中嵌入的Jython解释器。您也可以启动Jython解释器并将WLST加载到其中,以在Jython脚本中执行WLST命令。使用任何一种方法都可以发挥Jython语言的全部能力。

  下面是一个摘自环境供应脚本(WLST离线脚本)的片段:

weblogic_listen_port = int(profile[ 'managed.server.listen.port' ]) hostnames = profile[ 'managed.server.hosts' ] managed_server_count = len( hostnames ) for idx in range( managed_server_count ) : listen_address = hostnames[idx] interface_address = listen_address managedServer = create( managedServerName, 'Server') managedServer.setInterfaceAddress( interface_address ) managedServer.setListenAddress( interface_address ) managedServer.setListenPort( weblogic_listen_port )

  我没有展示它是如何创建的,但对象profile属于Python语言,它包含定义每个要供应的特定环境变量的键值对。这些值可以从一个或多个外部属性文件加载,也可以使用开始导入的Jython脚本设置。下面是一个Jython导入文件的等效示例:

def getProfile () : env = {} env['managed.server.listen.port'] = 7001 env['managed.server.hosts'] = \ [ "hostname_1", "hostname_2", "hostname_3" ] return env

  如果这在名为environment.py的Jython文件中,那么可以使用以下两行初始化profile对象:

import environment profile = environment.getProfile()

  注意如何使用Jython功能减少所需条目的数量。没有必要明确定义环境中受管服务器的数量:这可以从managed.server.hosts元素的内容中获得。

  我展示的只是一个非常简单的示例,但它说明了一些重要的适应性技术:

  • 供应脚本中导入了供应的变化方面。在本例中,它们从属性文件加载,但也可以通过单独的Jython脚本导入。
  • 脚本可以扩缩,不需要更改即可用于配置一个或多个受管服务器。
  • 脚本采用必需的模式,这些模式对于所有环境相同的。在本例中,模式是所有受管服务器使用的接口地址都与侦听接口相同,并且它们都使用相同的侦听端口。此外,受管服务器的唯一服务器名称的形式为<basename><index>,其中<basename>是所有服务器的共同点。示例中,<basename>是使用键值managedServerNameRoot从 dictionary元素中获得的,索引的值从1开始。这种配置模式在大型环境中很常见。

  现在,假设上述受管服务器始终是群集的一部分。配置群集时,您需要设置群集地址。群集地址可以设置为DNS名称,也可以是以逗号分隔的服务器IP地址和端口号所组成的列表。经验告诉我们,只有后期阶段的测试环境才配置DNS服务器。让我们向代码片段中加入一些次要的内容(并添加Jython导入):

 

  在这个修改过的代码片段中,您积累了一个以逗号分隔的服务侦听地址和端口所组成的列表。如果在配置文件中提供了DNS名称(本例没有),则可以使用其作为群集地址,但默认情况下使用积累的地址和端口列表。

端对端供应:共享配置数据

  在大部分测试环境中,供应的不仅仅是WebLogic域。例如,Apache Web服务器可以用于群集中受管服务器的静态HTTP目录或者平衡其HTTP请求的负载。供应脚本中也可以实现其他此类环境组件的配置。下面是一个environment.py的扩展版,包括了一个用于Apache Web服务器的配置值:

def getProfile () : env = {} env['managed.server.listen.port'] = 7001 env['managed.server.hosts'] = \ [ "hostname_1", "hostname_2", "hostname_3" ] env['apache.listen.port'] = 8080 return env

  要实现这一点,您需要向供应脚本添加几行代码(新增行添加到片段的最后面):

import environment profile = environment.getProfile() weblogic_listen_port = int(profile[ 'managed.server.listen.port' ]) hostnames = profile[ 'managed.server.hosts' ] managed_server_count = len( hostnames ) cluster_list = '' for idx in range( managed_server_count ) : listen_address = hostnames[idx] interface_address = listen_address managedServer = create( managedServerName, 'Server' ) managedServer.setInterfaceAddress( interface_address ) managedServer.setListenAddress( interface_address ) cluster_list = \ cluster_list + listen_address + ":" + str(weblogic_listen_port) if 'cluster.dns.name' in profile : cluster.setClusterAddress( profile['cluster.dns.name'] ) else : cluster.setClusterAddress( cluster_list ) f = open('weblogic.conf', 'w') f.write('<IfModule mod_weblogic.c>\n') f.write(' WebLogicCluster ') f.write(cluster_list) f.write('\n') f.write(' MatchExpression *.jsp\n') f.write('</IfModule>\n') f.close() f = None f = open('httpd.conf', 'w') f.write('Listen = ') f.write( str( profile[ 'apache.listen.port' ] ) ) f.write('\n') f.write('LoadModule weblogic_module modules/mod_wl_20.so\n') f.write('<IfModule mod_weblogic.c>\n') f.write(' Include conf/weblogic.conf\n') f.write('</IfModule>\n') f.close()

  最后面的行创建两个文件:httpd.conf和weblogic.conf,分别用于配置Apache Web服务器和WebLogic插件。下面是httpd.conf形式的输出内容:

Listen = 8080 LoadModule weblogic_module = modules/mod_wl_20.so Include conf/weblogic.conf

  下面是从environment.py生成的weblogic.conf:

 

<IfModule mod_weblogic.c>WebLogicCluster hostname_1:7001,hostname_2:7001,hostname_3:7001MatchExpression *.jsp  </IfModule>

  httpd.conf的配置使用键值 apache.listen.port,该键值从我们的environment.py文件中获得。但是要注意,插件的配置使用配置 WebLogic群集本身产生的副产品所累积的数据。WebLogic域配置数据曾经用于配置另一个相关的组件。这种配置数据的共享可以避免互相依赖的组件配置之间的不一致性。

  注意,这是使用的技术(即直接使用Jython编写配置)并不是很恰当,只有在配置文件很小的时候才适合这样做。实际操作中,包括Apache Web服务器文件在内的许多配置文件都很大,不能简单的这样处理。在这种情况下,最好使用Jython输出带有配置值的属性文件,然后使用 Ant导入该属性文件,并根据配置文件模式执行标记替换。从WLST脚本中使用Ant很简单:安装了 WebLogic Platform 8.1和9.x的情况下,BEA包含一个运行Ant的Jython脚本。

不要使用过多的参数

  编写适应性强的脚本的价值在于可以用于多个环境。但是,您不应该使用过多的参数。不要为不会随环境改变的属性和值创建参数,即使您的脚本会设置默认值。不必要的参数会使脚本更加复杂,使其变得更加难以理解。记住,您正试图创建的是可重用的脚本,可以在您进行其他项目之后仍然能被他人使用。每一个不必要的参数都会给您的继承者带来潜在的问题:“为什么所有环境采用相同值时要设置这个变量呢?我是不是哪里搞错了?”记住,您的继承者很可能有您的电子邮件地址和电话号码,会追问您可能早已不记得的事情!

0
相关文章