MQ群集的使用

Comments

从版本V5.1开始,MQ就增加了群集(Cluster)的功能,这是IBM MQ的特有优势之一。多个应用服务器之间的群集功能不仅使服务器之间能够共享负载,并且当某一系统或网络出现故障时,能够自动进行负载均衡;同时同一群集中的服务器可以位于不同的平台和物理位置。另外,群集功能使对服务器的管理更加简单高效。

为了能够使大家更好地理解和掌握群集的功能和用法,我们特推出此文章,说明群集在不同场合下的使用技巧及其配置步骤,并给出有关群集的系统管理策略。

1 群集的基本概念

首先我们先来谈谈群集的基本概念。

图1
图1

如图1所示,就MQ的点对点的通讯模式而言,我们需要创建相应的对象才能实现两个队列管理器之间的通讯,例如,在发送方队列管理器上,我们要创建一个远程队列(指向远程的目的队列),一个传输队列和一个发送类型的通道;在接收方队列管理器上,我们要创建一个本地队列和一个接收类型的通道。这样,当我们要实现一个网络当中的N个队列管理器之间的两两双向通讯时,我们需要配置的MQ对象的个数就会大大增长,比如,我们需要在每个发送方队列管理器上建立N个远程队列,N个传输队列以及N-1个发送类型的通道,这将组成一个复杂的网状结构,如图2所示。

图2
图2

采用群集的技术之后,可以大大简化系统配置,原因在于位于同一个群集当中的若干队列管理器之间互相通讯时,不需要在每一个队列管理器上创建消息通道、远程队列管理器以及与通道相关的传输队列的定义,相反,我们只需要为在每一个队列器上创建如下两个群集通道(MQ的通道分为三种类型,即服务器与服务器之间的消息通道,客户端与服务器之间的MQI通道,以及用于群集内部通讯的群集通道):

一个群集接收(cluster-receiver)通道,用来从群集中其他队列管理器接收应用消息和有关群集配置更新的消息;

一个群集发送(cluster-sender)通道,用来向群集发送应用消息和有关群集配置更新的消息。

这样,大大减少了位于群基内部的队列管理器上的MQ对象的总数,从而大大简化了系统的配置。如图3所示:

图3
图3

让我们先来了解一下有关群集的一些重要概念:

仓储库(Repository):仓储库是关于群集的信息集合,这些信息包括队列管理器的名字,它们的位置,它们所拥有的通道和队列等。这些信息存储在一个名为SYSTEM.CLUSTER.REPOSITORY.QUEUE中。仓储库又分为完全仓储库(Full Repository)和部分仓储库(Partial Repository)。完全仓储库包含了群集中所有队列管理器的有关群集的全部信息。与之对应,群集中的其他队列管理器拥有与其自身相关和它将要与之通讯的那些队列管理器的信息,成为部分仓储库队列管理器。部分仓储库队列管理器通过查询完全仓储库而得到群集信息的更新,为此,它们通过SYSTEM.CLUSTER.COMMAND.QUEUE队列向完全仓储库发送请求和接收信息。

仓储库队列管理器(Ropository queue manager):群集中拥有完全仓储库信息的队列管理器,一般情况下,我们在群集中选择两个队列管理器作为完全仓储库,互相形成备份。

群集队列(Cluster queue):在群集中共享的队列。宿主队列管理器拥有对该队列的本地定义,被共享后,群集中的其他成员都可以看到这个队列,并且向其发送消息,而不需要定义远程队列。

群集传输队列(Cluster transmission queue):群集中的每个队列管理器都有一个名为SYSTEM.CLUSTER.TRANSMIT.QUEUE的传输队列。

关于上述群集中对象的配置和定义,我们会在下面的例子中介绍。

2 群集的配置和使用实例

使用群集,概括而言主要有以下三个方面的优势:

  • 简化系统配置
  • 增强系统的高可用性
  • 增强系统的可扩展性

下面我们给出两个实例,帮助大家了解群集的使用和配置方法。

2.1 利用群集简化配置并进行负载均衡

通过本文第一部分讲述的群集基本概念,大家一定对群集简化系统配置的优势有了初步的认识;群集的第二个优势是提高系统的高可用性,假设A,B,C三个队列管理器位于一个群集中,A向B和C的队列发送消息,当B宕机时,C可以接管B的工作。

下面我们通过一个具体实例,给出一个典型群集的创建和配置步骤,来实现这两个优势。

如图4所示:

图4
图4

我们将创建一个名为CLUSTER1的群集,其中包含QMGR1,QMGR2和QMGRI三个队列管理器,其中在QMGR1和QMGR2上创建INPUTQ的接收队列,并使得它们在群集中共享。

配置步骤如下(以下各步中给出相应的MQSC命令):

1) 分别创建三个队列管理器

2) 设置QMGR1和QMGR2为群集的两个完全仓储库
在两个队列管理上执行MQSC命令:ALTER QMGR REPOS(CLUSTER1) MQSC命令

3) 定义三个队列管理器的群集发送和群集接收通道

  • 在QMGR1上执行MQSC命令:
    DEFINE CHANNEL(TO.QMGR1) CHLTYPE(CLUSRCVR) 
    TRPTYPE(TCP) CONNAME('9.68.58.228(1414)') CLUSTER(CLUSTER1)
    DEFINE CHANNEL(TO.QMGR2) CHLTYPE(CLUSSDR)  
    TRPTYPE(TCP) CONNAME('9.68.58.228(1415)') CLUSTER(CLUSTER1)
  • 在QMGR2上执行MQSC命令:
    DEFINE CHANNEL(TO.QMGR2) CHLTYPE(CLUSRCVR) 
    TRPTYPE(TCP) CONNAME('9.68.58.228(1415)') CLUSTER(CLUSTER1)
    DEFINE CHANNEL(TO.QMGR1) CHLTYPE(CLUSSDR)  
    TRPTYPE(TCP) CONNAME('9.68.58.228(1414)') CLUSTER(CLUSTER1)
  • 在QMGRI上执行MQSC命令:
    DEFINE CHANNEL(TO.QMGRI) CHLTYPE(CLUSRCVR) 
    TRPTYPE(TCP) CONNAME('9.68.58.228(1416)') CLUSTER(CLUSTER1)
    DEFINE CHANNEL(TO.QMGR1) CHLTYPE(CLUSSDR)  
    TRPTYPE(TCP) CONNAME('9.68.58.228(1414)') CLUSTER(CLUSTER1)

4) 在QMGR1和QMGR2上定义群集共享队列INPUTQ,在QMGR1和QMGR2上,分别执行MQSC命令:DEFINE QLOCAL(INPUTQ) CLUSTER(CLUSTER1)这时,在QMGRI上可以看到这两个被共享出来的队列

5) 验证配置成功在QMGRI上,利用MQ第一步中提供的例子程序API Exerciser,向INPUTQ发送消息,注意,在打开该队列的时候,一定要选择MQOO_BIND_NOT_FIXED选项,如图5所示:

图5
图5
图5

测试的结果表明,MQ将以轮巡的方式向QMGR1和QMGR2的INPUTQ发送消息,当我们停止队列管理器QMGR1时,所有的消息都会发送到QMGR2的INPUTQ中。

2.2 利用群集提高系统扩展性

群集的第三个优势是提高系统的可扩展性,这里我们也给出一个具体应用实例来加以说明,同时这里也涉及到群集内外队列管理器之间的通讯。

假设,某用户其总部和各个省公司之间传输数据,由于业务处理量较大,尤其是对总部而言,它是全国的通讯和业务枢纽,为了不让这里产生瓶颈,用户在这里设立多个应用服务器来进行交易处理,这里我们假设为两个。如何实现这样一种配置呢?

如图6所示:

图6
图6
图6

在总部建立三个队列管理器:QMGRHQ1,QMGRHQ2和QMGRGW,将这三个队列管理器组成一个群集CLUSTER1,QMGRA和QMGRB代表两个省的队列管理器,QMGRHQ1,QMGRHQ2位于应用服务器主机上。在这里我们要向大家指出的是:当群集内的队列管理器要和群集外的队列管理器通讯时,必须要设置一个网关队列管理器,利用该网关作为二者之间的桥梁,本例中QMGRWG即为网关队列管理器,它不对应用程序数据做任何处理,而仅仅起到路由的作用。而网关队列管理器和群集外的队列管理器之间的通讯配置必须遵循传统的MQ服务器之间点对点的配置方式,即要建立相应的传输队列、远程队列和消息通道等对象。

图6中的配置步骤如下:

1) 创建群集CLUSTER1,使QMGRHQ1,QMGRHQ2和QMGRGW成为该群集的成员,创建的方法同前例,在此不再赘述;

2) 在QMGRHQ1,QMGRHQ2上建立群集共享队列INPUTQ,在QMGR1和QMGR2上,分别执行MQSC命令:
DEFINE QLOCAL(INPUTQ) CLUSTER(CLUSTER1)

3) 在网关队列管理器QMGRGW上建立队列管理器别名ANY.CLUSTER,建立队列管理器别名的方法是建立一个RNAME属性为空的远程队列,在QMGRGW上执行MQSC命令:

DEFINE QREMOTE(ANY.CLUSTER) RNAME(' ') RQMNAME(' ')

4) 在QMGRA和QMGRB上建立传输队列和远程队列及通道,分别执行MQSC命令:

DEFINE QLOCAL(QMGRGW) USAGE(XMITQ)
DEFINE QREMOTE(TO.INPUTQ) RNAME(INPUTQ) RQMNAME(ANY.CLUSTER) XMITQ(QMGRGW)

通过上述配置,我们达到了这样的效果,当省级的队列管理器向总部的应用服务器的队列管理器QMGRHQ1和 QMGRHQ2发送数据时,消息将会首先被发往网关队列管理器QMGRGW,然后通过它被路由到QMGRHQ1和 QMGRHQ2上,从而被应用程序处理。这样一来,我们将业务负载均衡到了总部的多台服务器上,并且随着业务量的增加,我们可以随时增加主机,并且做到了对客户端的省级服务器的透明性,就此提高了整个系统的扩展性。

同理,当我们要做反向通讯时,即我们要借助网关队列管理器从总部的QMGRHQ1和 QMGRHQ2向省级的QMGRA发送消息时,我们只需要增加如下配置:

在QMGRGW上,创建在群集中共享的远程队列定义,执行MQSC命令:

DEFINE QREMOTE(PROVINCE.RECEIVE) RNAME(PROVINCE.RECEIVE) RQMNAME(QMGRA) CLUSTER(CLUSTER1)

在QMGRA上,创建本地队列定义,执行MQSC命令:

DEFINE QLOCAL((PROVINCE.RECEIVE)

3 有关群集的系统管理和使用技巧

以上我们给出了使用群集的两个典型实例,从中大家可以体会到有关群集配置时的一些方法和步骤,接下来,我们对使用群集中的一些规律技巧和群集管理方面的内容跟大家做一个简单探讨。

3.1 群集的操作和管理

先来了解一下与群集相关的MQ命令。

  • DISPLAY CLUSQMGR(name):显示群集中所有队列管理器的信息
  • SUSPEND QMGR CLUSTER(cluster):通知群集中的其他队列管理器,表明该队列管理器暂时不可用,要注意的是,这并不意味着将该队列管理器从群集当中彻底移走。
  • RESUME QMGR CLUSTER(cluster):对应于SUSPEND命令,在群集中重新恢复对该队列管理器的使用。
  • REFRESH CLUSTER(cluster):对该命令要特别注意,千万不能从名字上去理解它的作用,它将破坏所有本地保留的与群集相关的信息,包括所有自动定义的群集通道。
  • RESET CLUSTER(cluster) QMNAME(name) ACTION (FORCEREMOVE):该命令用于仓储库队列管理器。它将通知仓储库某队列管理器被从群集中删除。

以上的几个命令仅仅是群集操作的基本命令,这里,我们进一步举例说明常见的一些有关群集系统管理的处理办法。

  • 从群集中除去队列管理器
    1) 使用SUSPEND命令暂停队列管理器在群集中的角色
    2) 使用stop chl命令停止该队列管理器的CLUSRCVR通道
    3) 利用alter chl(name) chltype(clusrcvr) cluster(' ')命令,通知仓储库该队列管理器离开群集
    4) 使用stop chl命令停止该队列管理器的CLUSSDR通道
    5) 删除该队列管理器的CLUSSDR和CLUSRCVR通道
  • 从群集中除去群集共享队列
    1) 使用alter ql(name) put(disabled) 命令停止对该队列的操作
    2) 确保该队列为空以及与此队列相关的发送通道上不存在尚未提交的消息,相关的命令有:
    3) dis ql(name) ipprocs opprocs curdepth
    4) dis chs(*) indoubt
    5) 使用delete ql命令删除该队列或使用alter ql(name) cluster(' ')命令将该队列从群集中除去
  • 向群集中增加队列管理器
    1) 为该队列管理器建立通往仓储库的CLUSSDR和CLUSRCVR通道
    2) 启动CLUSSDR通道,这将会使得该队列管理器自动向群集广播它的加入
    3) 更改群集中的仓储库队列管理器
    使用alter qmgr repos(clustername)命令将此队列管理器设置为群集的仓储库
    4) 显式地定义该队列管理器和其他仓储库队列管理器之间的CLUSSDR通道,并且启动这些通道
    5) 显式地定义其他仓储库和该队列管理器之间的CLUSSDR通道,并且启动这些通道
    6) 使用alter qmgr repos(' ')命令除去原来的队列管理器的repository属性
    7) 在群集的其他队列管理器上除去那些显式定义的指向原来仓储库队列管理器的CLUSSDR通道
    8) 在群集的其他队列管理器上新建指向新建仓储库队列管理器的CLUSSDR通道

3.2 群集的设计和使用指导

3.2.1 关于群集的可行性设计

在规划MQ系统网络的时候,大家最为关心的问题就是采用群集对网络负担的影响,一个群集到底能够支持和容纳多少个队列管理器等问题,这些也是我们在分析是否采用群集这种解决方案的要考虑的一些因素。

根据相关数据资料显示以及我们与国外同行的交流,IBM在试验室中曾经创建过含有上千个队列管理器的群集,并且当运行数百个共享队列实例时,整个系统的负载仅仅增加了10%。一个群集的物理限制并不来源于群集本身,而是队列管理器本身所能够支持的最多队列、最多运行的通道等对象的数目。例如,群集本身会自动创建一些通道,但是同时运行的通道个数还是来自于队列管理器本身的限制和配置。

另外,大家关心使用群集是否会加大网络负载,由于群集队列管理器之间要同步更新一些有关群集配置变化的信息,比如,这些信息要通过仓储库队列管理器通知群集的所有成员。对于这一点,我们希望指出的是,这种信息的数量取决于你的群集中的有关对象配置的变化频率和数量,一般来说,我们会在最初设计群集的时候进行全面细致的规划和设计,而不会导致在群集运行过程中,频繁地更改共享队列的配置,或把某个队列管理器频繁地移进移出,这样,就不会导致群集配置信息在群集中的频繁更新,从而不会给网络带来相应的负荷。另外,在群集规模非常大,群集中包含的队列管理器比较多时,我们也可以采取划分多个群集,再通过网关把它们互连的解决办法。

3.2.2 群集信息在仓储库中保留的时间

当群集中的队列管理器向仓储库发送关于自身的有关更新信息时,比如,它新建了一个队列等,这些更新信息在仓储库当中会被保留30天,为了防止信息超时,队列管理器将在27后自动向仓储库发送所有有关自身的配置信息。当信息超时后,仓储库并不立即将其删除,而是继续将其保留60天。如果在这附加的60天之内,仓储库仍然没有收到更新信息,这些信息将会被从仓储库清除掉。例如,如果某个队列管理器与群集断开连接超过90天,它将不再是群集中的成员。但是,当它重新恢复与群集的连接时,它将又自动恢复为群集中的一员。

这一点是需要注意的,如果在测试环境中,不慎更改了系统时间,可能会由于这个原因导致群集不可用。

3.2.3关于共享队列实例和消息的走向

群集允许定义同一个队列的多个队列实例(queue instance),每一个位于不同的队列管理器上。当我们把消息发到这些实例时,MQ系统来决定将其路由到哪个队列管理器的哪个队列上。例如:在我们给出的第一个例子中,在QMGRI上可以看到两个INPUTQ的实例,它们的宿主队列管理器分别是QMGR1和QMGR2。当我们在QMGRI上向INPUTQ发送消息时,消息被会分发到其他两个队列管理器上。这里我们需要注意以下几个要点:

1) 如果在发送消息的应用程序本地的队列管理器上有队列实例存在,即该队列管理器是队列实例的宿主队列管理器时,消息将只会被发到该队列,而不会被分发到其他队列实例上。还以我们给出的第一个例子为例,如果在QMGRI上也存在INPUTQ队列,则消息将会全部被发往该队列。

2) 关于消息的亲合特性(affinity),如果对消息顺序有要求或者若干个消息必须进行逻辑组合处理,那么我们就不能将这些消息分别路由到不同队列管理器上,这时,我们需要使用BIND_ON_OPEN选项来实现这种需求。

3.2.4 关于打开队列选项的使用

为了使用群集的负载均衡功能,MQ 的API接口函数MQOPEN增加了两个新的选项:MQOO_BIND_ON_OPEN和MQOO_BIND_NOT_FIXED。注意,它的缺省值为MQOO_BIND_ON_OPEN,这样对每一次MQOPEN操作,负载均衡算法将只被调用一次,从而导致消息将只被发送到其中一个队列实例中。因此,大家如果希望使用轮循处理机制,必须将该选项设置为MQOO_BIND_NOT_FIXED。

通过本文对群集功能及使用的简单介绍,希望大家在实际应用中能够采用群集的解决方案,以发挥MQ产品的更多优势。


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=163359
ArticleTitle=MQ群集的使用
publish-date=10012003