级别: 初级 Jane Stockdill (STOCKD@uk.ibm.com), 开发人员, IBM Hursley
2004 年 10 月 01 日 许多 WebSphere® MQ Everyplace 用户都建立了到 WebSphere MQ 的网关,但是却没有关于如何完成这项常见任务的最佳实践。本文提供在 WebSphere MQ 与 WebSphere MQ Everyplace 之间建立网关的指导和范例代码,这使得该项任务更具价值。本文的目标读者是使用 WebSphere MQ 或 WebSphere MQ Everyplace 的人员,但并不需要很多编程知识,因为您可以使用 SupportPac 脚本工具进行设置。
引言
本文提供了循序渐进的指导,以帮助您使用 WebSphere MQ Everyplace Gateway V2 建立多个客户端连接和网桥队列,从而获得最佳消息吞吐量。同时提供了 MQe_Script 命令来创建这些对象(尽管也可以使用其它 WebSphere MQ Everyplace 工具或管理消息来创建它们)。
本文没有提供关于如何创建必要的 WebSphere MQ 对象的指导或代码,因此您应该参考 WebSphere MQ 提供的
用户文档或
MQe_Script supportPac 提供的范例。
本文需要您具备 WebSphere MQ Everyplace 和 WebSphere MQ 的相关知识。
性能关系
当使用 WebSphere MQ Everyplace 时,您可以创建网关来使消息流向 WebSphere MQ。您将需要创建一些 WebSphere MQ Everyplace 对象来配置该网关。这些对象包括网桥、队列管理器代理、客户端连接、网桥队列,并且如果消息需要从 WebSphere MQ 返回到 WebSphere MQ Everyplace 的话,还可选用传输队列监听器。
在标准配置中,单客户端连接连同单个网桥队列一起创建。这就足以将消息从 WebSphere MQ Everyplace 发送到 WebSphere MQ。
如果有多个客户端(数量很大)连接到网关,那么每秒发送到 WebSphere MQ 的消息数量将会减少。
网关配置
如图 1 所示,如果有多个客户端经过通信监听器连接到网关队列管理器,网桥队列将会产生瓶颈。为了减轻该问题,您可以创建多个网桥队列、客户端连接、服务器连接通道以及同步队列。
图 1. WebSphere MQ Everyplace 网关标准配置
随着网桥队列数量的增加,网关性能降低,此时关于决定网桥队列的创建数量的问题务必谨慎。
性能增强
通过创建使用多个网桥队列的 WebSphere MQ Everyplace 网络,每秒经过网关发送的消息数量将会显著增加。
每秒经过网关发送的消息数量不仅仅依赖于您的网关配置,还与其他一些问题相关,比如所发送消息的类型、网络配置以及硬件。
在一个测试场景中,我们发现当大约有 1,350 个客户端连接到网关时,10 个网桥队列比单个网桥队列每秒发送的消息数量高 34 倍。当网桥队列增加到 50 个时,会比单个网桥队列每秒发送的消息数量高 86 倍。但如果网桥队列增加到 1350 个,则吞吐量的增长又降回到 34 倍。
请注意这种增长只与发送到 WebSphere MQ Everyplace 的消息相关,而不涉及从 WebSphere MQ Everyplace 接收到的消息。
寻找和创建最佳配置
要为您的设置寻找最佳配置,需要创建 WebSphere MQ Everyplace 对象并执行测试来衡量消息吞吐量。这些经验性的测试最好在与实际产品网络类似的网络上进行,并使用实际产品类型的消息数据。
使用 SupportPac MQe_Script 来创建测试既易于配置又可重复使用。SupportPac 是一个基于命令行的工具,它用于创建和管理 WebSphere MQ Everyplace 资源。MQe_Script 嵌入了名为 TCL 的脚本语言,您可以使用该语言来编写添加逻辑和控制的智能脚本。您可以从业务集成 SupportPacs Web 站点上
下载 SupportPac。要从该站点下载,请从列表框中选择 WebSphere MQ Everyplace 产品。
使用 MQe_Script,您可以编写该脚本以创建网关上所有必要的对象,以及任意客户端。可以将参数传入脚本,通过这种方式就可以用脚本指定所需的网桥队列的数量。脚本运行的结果是,网桥队列和所有其它相关的 WebSphere MQ Everyplace 对象被创建。
通过使用这种方法来创建 WebSphere MQ Everyplace 配置,您可以快速且很容易的对所需的网桥队列数量进行试验,以达到理想的吞吐量。您只需要编写脚本,除此之外无需其他编程。
MQe_Script 甚至可以用来修改任何现有的配置。
虽然 MQe_Script 并不修改 WebSphere MQ 对象,但这些对象可以使用 MQSC 命令来创建。MQe_Script 附带了一个 MQSC 脚本范例,说明了如何创建与 WebSphere MQ Everyplace 网关通信所必需的 WebSphere MQ 对象。
设立网关
以下是建立网关所需的内容:
- 网关需要一个网桥对象的实例,以及一个 WebSphere MQ 队列管理器代理对象的实例
-
接下来,您需要创建客户端连接对象。需要创建多少个客户端连接对象,这取决于需要多少个网桥队列。
- 最后,您需要创建创建网桥队列,每个队列使用不同的客户端连接。
设立客户端
每个客户端必须有一个到 WebSphere MQ 队列的远程队列定义。如果网关上使用了多个网桥队列,远程队列定义需要有别名,这样任何发送消息的应用程序都可以通过客户端获取到 WebSphere MQ 队列的正确路径。这也使得应用程序不需要知道客户端处于哪个队列。
例如,如果现有 3 个客户端,每个客户端处于单独的网桥队列 b1、b2 和 b3,所有的远程队列定义可以有 b 的别名。那么客户端的任何应用程序就可以简单的发送到队列 b。这允许底层网络的修改,而不需要对应用程序做任何修改。
要想利用网关上的所有网桥队列,从而达到最佳消息吞吐量,网桥队列就需要在全部的客户端中平均分配。这就是说,如果有 50 个网桥队列和 5,000 个客户端,那么就应该有 100 个客户端创建到 bridgeq1 的远程队列定义,另外 100 个创建到 bridgeq2 的远程队列定义,依此类推。
创建网关的步骤
以下是创建网关的基本步骤和代码片断。在本部分使用的 MQe_Script 命令以及未经定义的变量将在本文的后面作为完整的脚本提供。
- 创建队列管理器。
要创建基本队列管理器,需要提供名称和磁盘位置。磁盘位置是保存注册表以及队列消息的地方。请参阅下面的清单 1 中的代码范例。
清单 1. 创建队列管理器的代码片断
mqe_script_qm -create -qmname $GATEWAYQM -qmpath $PATH |
- 启动队列管理器
这里使用的命令没有指定要装载的队列管理器名称。这是因为如果在创建命令后直接使用,队列管理器详细信息将被缓存。要获取关于如何载入先前创建的队列管理器的信息,请参阅 MQe_Script 附带的文档。请看下面清单 2 中的代码范例。
清单 2. 启动队列管理器的代码片断
- 创建监听器。
必须为监听器指定要监听的名称和端口。如果与缺省值(TCPIP HTTP)不同,可以指定适配器类型。参见下面清单 3 中的代码范例。
清单 3. 创建监听器的代码片断
mqe_script_listen -create -listenname $LISTENER -port $GATEWAYPORT |
- 启动监听器。
在缺省情况下,监听器在创建之后并不启动。然而,一旦队列管理器终止并重新启动,监听器将自动启动。参见下面清单 4 中的代码范例。
清单 4. 启动监听器的代码
mqe_script_listen —start -listenname $LISTENER |
- 创建网桥。
需要为网桥对象指定一个任意的名称。它作为全部其他网桥相关对象的父对象。参见下面清单 5 中的代码范例。
清单 5. 创建网桥的代码片断
mqe_script_bridge -create -bridgename $BRIDGE
|
- 创建队列管理器代理。
队列管理器代理必须与先前创建的网桥对象相关联。它的命名也必须依照将发生连接的 WebSphere MQ 队列管理器的名称。最后,需要定义 WebSphere MQ 队列管理器的计算机的 IP 地址或主机名。参见下面清单 6 中的代码范例。
清单 6. 创建队列管理器代理的代码片断
mqe_script_mqproxy -create -proxyname $PROXY -bridgename $BRIDGE
-hostname $ADDRESS
|
- 创建到 WebSphere MQ 队列管理器的连接定义。
必须创建特定的 MQ 连接来定义 WebSphere MQ 队列管理器。这需要和 WebSphere MQ 队列管理器的名称相同。参见下面清单 7 中的代码范例。
清单 7. 创建到 WebSphere MQ 队列管理器的连接定义
mqe_script_condef -create -cdname $PROXY -type mq
|
- 要接收从 WebSphere MQ 返回的消息,需要创建多个传输队列监听器,这一步是可选的。
如果需要传输队列监听器,就必须与先前创建的客户端连接通道、队列管理器代理和网桥对象相关联。传输队列监听器必须和 WebSphere MQ 队列管理器上的传输队列名称相同。参见下面清单 8 中的代码范例。
清单 8. 创建多个传输队列监听器
mqe_script_mqlisten -create -listenname $LISTEN
-clientconnname $CC$j -proxyname $PROXY -bridgename $BRIDGE
|
- 创建多个网桥队列。
必须为网桥队列提供名称。在通常情况下,网桥队列名称反映了 WebSphere MQ 目的地队列的名称。用于将网桥队列连接到 WebSphere MQ 队列的一个替换的方法是使用附加参数 MQ Queue Name,它允许网桥队列具有不同的名称。当定义多个网桥队列时,需要使用后一种方法。每个网桥队列必须与单独的客户端连接相关联。换句话说,就是一对一的关系。网桥队列还需要与网桥以及队列管理器代理相关联,因此,需要将网桥队列联系到特定的 WebSphere MQ 队列管理器、队列和连接。参见下面清单 9 中的代码范例。
清单 9. 创建多个网桥队列
mqe_script_bridgeq -create -qname $BRIDGEQ$j -bridgename $BRIDGE
-destination $PROXY -mqqname $REALBRIDGEQ -clientconnname $CC$j
|
- 启动网桥。
启动网桥时也将缺省启动所有的子对象。如果您已经创建了传输队列监听器,并且您的 WebSphere MQ 队列管理器不具有可联系性(contactable),那么这将导致传输队列监听器启动失败。即使所有的子对象都没有启动,当命令成功返回时,也应该提防这个问题。否则,将会抛出一个错误,您可能希望忽略该错误并继续执行脚本。如果您愿意的话,每个子对象都能够单独启动。参见下面清单 10 中的代码范例。
清单 10. 启动网桥的代码片断
mqe_script_bridge -start -bridgename $BRIDGE
|
创建客户端的步骤
创建客户端的基本步骤在下面定义。与之相应的 MQe_Script 命令以及未定义的参数将在本文后面提供。
- 创建队列管理器。
提供名称和磁盘位置。参见下面清单 11 中的代码范例。
清单 11. 创建队列管理器的代码片断
mqe_script_qm —create —qmname $CLIENT —qmpath $PATH
|
- 启动队列管理器。
参见下面清单 12 中的代码范例。
清单 12. 启动队列管理器的代码片断
- 创建到网关队列管理器的连接定义。
连接定义必须具备与网关队列管理器相同的名称。定义网关监听的的端口,如果网关监听非默认的适配器,那么这也需要定义。参见下面清单 13 中的代码范例。
清单 13. 创建到网关队列管理器的连接定义的代码片断
mqe_script_condef —create —cdname $GATEWAYQM
—port $PORT —address $ADDRESS |
- 创建到 WebSphere MQ 队列管理器的通路连接定义。
客户端必须了解 WebSphere MQ 队列管理器,以便将消息放到它的队列中。当通路连接的名称与 WebSphere MQ 队列管理器名称相同,并且通路名称与网关队列管理器名称相同时,就可以创建通路连接。参见下面清单 14 中的代码范例。
清单 14. 创建到 WebSphere MQ 队列管理器的通路连接定义的代码片断
mqe_script_condef —create —cdname $MQNAME —viaqmname $GATEWAYQM
|
- 创建到网桥队列的远程队列定义并添加别名。
远程队列定义的名称必须匹配于网关上定义的一个网桥队列。WebSphere MQ 队列管理器的队列管理器名称也必须被定义。
当网桥队列名称与真实的 WebSphere MQ 队列名称不同时,要使用多个网桥队列,就必须使用别名。应用程序不能使用网关上的网桥队列名称作为 WebSphere MQ 队列的名称,这是因为该队列并不存在于 WebSphere MQ 队列管理器中。
同样,队列的远程定义不能被称为是真实的 WebSphere MQ 队列名称,这是由于该引用不存在于网关队列管理器中。因此,将 WebSphere MQ 队列的实际名称作为别名添加到远程队列定义中是很有用的,这样应用程序就可以正确的知道消息应该发送到何处。参见下面清单 15 中的代码范例。
清单 15. 创建到网桥队列的远程队列定义并添加别名
mqe_script_sproxyq —create —qname $BRIDGEQ$BRIDGEQNUM
—destination $MQNAME —alias $REALBRIDGENAME
|
当使用 MQe_Script 时,别名可以在创建时期添加,如果远程队列定义已经存在,别名也可以在后面的阶段中进行更新。
- 通过将消息从客户端发送到 WebSphere MQ 队列管理器来测试连接。
为了应用程序进行相同的调用以及放置消息的客户端的独立性,可以使用远程队列定义的别名来放置消息。参见下面清单 16 中的代码范例。
清单 16. 测试连接的代码片断
mqe_script_msg —put —qname $REALBRIDGENAME —qmname $MQNAME
|

 |

|
编写脚本的技巧
当编写脚本时,在脚本开头定义一组变量通常会更简便。这使得任何对命名约定或 WebSphere MQ Everyplace 对象数量的修改更易于管理。
在 TCL 中,使用 set 命令来定义变量,并且引用变量时,在变量前面使用 $ 标记。
用大写字母来定义变量也很有用,这样就使得这些变量在脚本中更容易识别。参见下面清单 17 中的代码范例。
清单 17 定义 PATH 变量的代码
set PATH "C:\\MQeScript\\gateway"
|
当调用 MQe_Script 命令时,它们可以在自己的脚本中定义,或者可以添加 TCL 控制结构以在命令成功提供反馈,并且如果发生错误,可能会退出脚本。
检查命令是否成功的一个方法是使用 catch 命令的 if / else 代码块。参见下面清单 18 中的代码范例。
清单 18. 使用 catch 命令的 if / else 代码块来检验命令是否成功的代码
if { [catch {mqe_script_qm -create
-qmname $GATEWAYQM -qmpath $PATH} error] } {
puts "An error occurred creating queue manager";
puts "The reason was: $error"
exit
} else {
puts "Queue manager created"
}
|
如清单 18 中的代码片断所示,puts 命令用来将文本打印到屏幕,exit 命令终止脚本的执行。如果抛出任何错误,错误文本将保存在名为“error”的变量中,该变量可以被访问。
如果脚本正在编写,用于创建用变量定义的大量网桥对象,这些对象的创建可以放在一个循环中。创建多个对象最简单的方法是对每个对象使用标准名称,然后对每个名称加上一个数字,这样这些名称就都是唯一的了。参见下面清单 19 中的代码范例。
清单 19
for {set j 1} {$j <= $QNUM} {incr j} {
#create all the client connections
mqe_script_mqconn -create -clientconnname $CC$j
-proxyname $PROXY -bridgename $BRIDGE -syncqname $SYNCQ$j -port $PORT
}
|
清单 20 演示了如何使用循环变量来创建名称。$CC 已经被定义为客户端连接名称前缀,$SYNCQ 被定义为同步队列名称前缀。
清单 20 中的代码片断也说明了用 # 标记来定义注释。
要使用脚本文件来提供 MQe_Script,它必须用 tcl 扩展来保存,提供脚本的命令是
source 命令。参见下面清单 20 中的代码范例。
清单 20
source {C:\MQeScript\gatewayscript.tcl}
|
要获取更多关于 TCL 和编写脚本的信息,请参阅 MQe_Script 附带的文档。
创建网关的脚本范例
您可以使用下面的范例来创建网关。
清单 21. 创建网关的脚本范例
set PATH "C:\\MQeScript\\gateway"
set ADDRESS 127.0.0.1
set GATEWAYQM gatewayqm
set LISTENER listener
set GATEWAYPORT 1881
set PROXY QM_jane
set BRIDGE bridge
set REALBRIDGEQ mqlocalq
set CC FOR.GATEWAYQM.
set LISTEN togateway
set BRIDGEQ bridgeq
set SYNCQ SYNC.QUEUE.
set PORT 1414
set QNUM 50
#create the gateway queue manager
if { [catch {mqe_script_qm -create -qmname
$GATEWAYQM -qmpath $PATH} error] } {
puts "An error occurred creating queue manager";
puts "The reason was: $error"
exit
} else {
puts "Queue manager created"
}
#load the queue manager
if { [catch {mqe_script_qm -load} error] } {
puts "An error occurred loading queue manager";
puts "The reason was: $error"
exit
} else {
puts "Queue manager loaded"
}
#create the listener
if { [catch {mqe_script_listen -create -listenname
$LISTENER -port $GATEWAYPORT} error] } {
puts "An error occurred creating a listener";
puts "The reason was: $error"
exit
} else {
puts "Listener created"
}
#create a bridge
if { [catch {mqe_script_bridge -create -bridgename $BRIDGE} error] } {
puts "An error occurred creating bridge";
puts "The reason was: $error"
exit
} else {
puts "Bridge created"
}
#create a mq proxy
if { [catch {mqe_script_mqproxy -create -proxyname
$PROXY -bridgename $BRIDGE -hostname $ADDRESS} error] } {
puts "An error occurred creating proxy";
puts "The reason was: $error"
exit
} else {
puts "MQ queue manager proxy created"
}
#create a connection to the WebSphere MQ queue manager
if { [catch {mqe_script_condef -create -cdname
$PROXY -type mq} error] } {
puts "An error occurred creating connection
for the MQ queue manager";
puts "The reason was: $error"
exit
} else {
puts "Connection to MQ queue manager created"
}
#create the client connections, listeners and bridge queues
for {set j 1} {$j <= $QNUM} {incr j} {
#create all the client connections
if { [catch {mqe_script_mqconn -create -clientconnname
$CC$j -proxyname $PROXY
-bridgename $BRIDGE -syncqname $SYNCQ$j -port $PORT} error] } {
puts "An error occurred creating client connection $CC$j";
puts "The reason was: $error"
exit
} else {
puts "client connection created"
}
#create all the listeners on the new client connections
if { [catch {mqe_script_mqlisten -create -listenname
$LISTEN -clientconnname $CC$j
-proxyname $PROXY -bridgename $BRIDGE} error] } {
puts "An error occurred creating listener
$LISTEN on client connection $CC$j";
puts "The reason was: $error"
exit
} else {
puts "listener created"
}
#create all the bridge queues
if { [catch {mqe_script_bridgeq -create -qname
$BRIDGEQ$j -bridgename $BRIDGE
-destination $PROXY -mqqname
$REALBRIDGEQ -clientconnname $CC$j} error] } {
puts "An error occurred creating bridge queue $BRIDGEQ ";
puts "The reason was: $error"
exit
} else {
puts "bridge queue created"
}
}
# We've finished the script... lets close the queue manager
if { [catch {mqe_script_qm -unload} error] } {
puts "Failed to stop the queue manager"
puts "The reason was: $error"
exit
} else {
puts "Queue manager stopped"
}
puts "CreateGatewayQM script completed successfully"
exit 0
|
创建客户端的脚本范例
这个脚本只说明了保存副本的基本 MQe_Script 命令。控制结构可以围绕命令而放置,或者可以直接运行。
要是这个脚本成功运行,通过网关脚本创建的队列管理器必须作为 WebSphere MQ 队列管理器来运行。
清单 22. 创建客户端的脚本范例
set CLIENT client1
set PATH "C:\\MQeScript\\client"
set ADDRESS 127.0.0.1
set GATEWAYQM gatewayqm
set PORT 1881
set BRIDGEQ bridgeq
set BRIDGEQNUM 1
set REALBRIDGENAME mqlocalq
set MQNAME QM_jane
mqe_script_qm —create —qmname $CLIENT —qmpath $PATH
mqe_script_qm —load
mqe_script_condef —create —cdname $GATEWAYQM —port $PORT —address $ADDRESS
mqe_script_condef —create —cdname $MQNAME —viaqmname $GATEWAYQM
mqe_script_sproxyq —create —qname $BRIDGEQ$BRIDGEQNUM —destination $MQNAME —alias $REALBRIDGENAME
mqe_script_msg —put —qname $REALBRIDGENAME —qmname $MQNAME
|
结束语
使用多个网桥队列和客户端连接对象可以显著提高从 WebSphere MQ Everyplace 到 WebSphere MQ 的消息吞吐量。但没有关于这些性能提高的具体图表,这是因为它不仅仅取决于 WebSphere MQ Everyplace 配置。
MQe_Script 可以用来创建这些配置,它能够进行简单的修改来影响多少个对象将被创建,这是为您的设置达到最佳对象数量的关键部分。
下载
参考资料
关于作者  | 
|  | Jane Stockdill 是 IBM Hursley 的一名软件开发人员,在过去的四年里,她一直从事 WebSphere MQ Everyplace 方面的工作。
|
对本文的评价
|