内容


任务:消息

WebSphere MQ 集群中的迁移、故障转移和扩展

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 任务:消息

敬请期待该系列的后续内容。

此内容是该系列的一部分:任务:消息

敬请期待该系列的后续内容。

在每个专栏中,“任务:消息”讨论的主题旨在鼓励您重新检查您对 IBM® WebSphere® MQ 及其在您的环境中的作用的看法,以及为什么您应该定期地注意它。

消息对 SOA 的影响

任务:消息的前一部分中,我曾写到从点对点消息体系结构到面向服务的发展要求更新消息领域中的许多长期存在的最佳实践。这里,我们将考虑一个案例研究,以了解队列管理器的迁移、故障转移和扩展,以及在 SOA 的上下文中考虑这些活动时对命名约定、工具、管理流程和操作的影响。

首先让我们了解一些术语:

  • 本讨论中的迁移包括任何重新承载队列管理器的情况,也许是为了更新基础硬件或者为了移动到不同的平台。迁移将始终涉及到构建新的队列管理器、将应用程序和队列逻辑地移动到新的队列管理器,以及最终使旧的队列管理器退役。

  • 故障转移是主系统在计划内或计划外的关闭,并包括完成将备用节点置于在线以接管处理负载的任务。补充操作在主节点恢复时退回主节点。典型示例是灾难恢复测试,其中涉及故障转移到热备用系统、测试应用程序,然后退回到主系统。

  • 水平扩展的定义是更改集群中的输入队列的并发实例数量,以便增加或减少处理容量。水平扩展以适应增长通常是永久性的。扩展以适应高峰处理季节是首先增加然后减少容量的周期性过程。扩展过程可能涉及也可能不涉及构建新的队列管理器,并且通常不涉及对现有实例的任何更改。

面向服务的某些方面最适合使用 IBM WebSphere MQ 集群来提供。集群可以提供位置独立性、运行时名称解析,以及 SOA 应用程序所需要的并发性。由于这些原因,SOA 的采用正在推动从点对点消息网络到集群环境的迁移。

点对点范式

大多数历史悠久的 WebSphere MQ 工作室都会至少遇到一次硬件迁移,并体验到足够多的增长以致要求在某个时候进行扩展,因此可能存在用于这些活动的既定过程。但愿所有团队都拥有灾难恢复计划,甚至是刚开始使用 WebSphere MQ 的团队。这些过程应该是什么样的呢?在点对点的世界中,迁移、故障转移和扩展通常是不同的,彼此之间千差万别。

  • 迁移:将迁移作为单个事件来计划和实施是非常普遍的,其中所有的任务都在不间断的序列中进行,包括新的目标队列管理器上的大量构建和配置活动。通过这种方式,可以捕获即将退役的队列管理器的当前状态,并将其毫发无损地移动到新的主机。由于是一次性的活动,因此很少有(如果有的话)退回的余地。

  • 故障转移:故障转移的目标是在两个功能等效的队列管理器之间切换。尽管它们是(至少应该是)具有不同名称的不同队列管理器,但是对于网络的其他部分来说,两者之间的唯一明显区别是 CONNAME。由于故障转移始终预期要退回,因此花时间创建可促进活动一致、可靠和可重复执行的自动化或流程是值得的。通常,故障转移涉及到一个独立于实际切换执行的扩建阶段。

  • 扩展:与适应周期性负载相比,升级容量是更常见的扩展情况。因此,大多数扩展情况都是计划的,并作为一次性的事件来执行,这一点与迁移类似。主要的区别在于,在该事件之后,将创建过程以确保队列管理器的所有实例保持同步,并将应用于一个实例的更改应用于所有的实例。

点对点实现

在此体系结构中,队列管理器是对象名称的根上下文,用于管理和操作的过程反映了这种倾向。由于在点对点网络中更改队列管理器名称具有干扰性,因此在故障转移和迁移过程中对队列管理器和通道重用相同的名称非常有诱惑力。这实际上是一种反模式;有些主意起初看起来像是正确的想法,但后来通常证明是一场噩梦,这就是其中之一。尽管队列管理器名称重用存在问题,我看到过的大多数迁移计划还是依赖于它。结果,要让两个队列管理器同时在线将非常困难或根本不可能,从而影响迁移任务的计划和执行。

在可扩展性的情况下,其中的主要目标是并发性,重用队列管理器名称导致的问题比它解决的问题还多,因此通常不存在创建重复命名的实例的诱惑。在此情况下,通常使用队列管理器别名来实现节点等效性,但是总体效果仍然是在其队列管器的上下文中解析队列。

点对点体系结构的另一个方面在于,运行时配置往往保持相当的静态。事实上,许多流程和过程假设配置具有稳定性。例如,以对象定义的情况为例。在许多工作室中,对象定义存储在 mqsc 脚本中。该脚本的初始版本包含队列管理器的本地基准,例如设置死信队列、锁定远程管理访问以及优化通道。然后,特定于应用程序的对象添加在各自的脚本中或添加到主脚本。随着新队列、主题和其他对象的添加,脚本被再次运行。此操作重新定义了已有的现有对象并创建任何新对象。典型的示例类似如下:

清单 1
DEFINE QLOCAL (APP.FUNCTION.SUBFUNCTION.QA) +
       DESCR('APP service queue for QA') +
       BOTHRESH(5) +
       BOQNAME('APP.FUNCTION.BACKOUT.QA') +
       CLUSTER('DIV_QA') +
       CLUSNL(' ') +
       DEFBIND(NOTFIXED)
       REPLACE

第一次运行此定义时,创建了本地队列 APP.FUNCTION.SUBFUNCTION.QA。REPLACE 选项确保该定义在后续运行时不会生成错误。这里的关键在于,所有的网络维护活动均在构建时执行。这里的例外是故障转移。由于故障转移被设计在系统之中,执行它的脚本和补充退回脚本通常是预先创建的。通常,还存在 mqsc 脚本,但是与包括 DEFINE 语句不同,它们包括类似如下的 ALTER 语句:

清单 2
ALTER CHANNEL(QM1.QM2) CHLTYPE(SDR) +
       CONNAME('host.of.qm2(1414)')
       PUT(DISABLED) 
	
RESET  CHANNEL(QM1.QM2)

这样将创建一组执行故障转移的脚本和另一组执行退回的脚本。尽管这些脚本在运行时执行,但是值得注意的是,它们使用与构建时活动相同的工具。还要注意,消息的路由是通过重新连接物理网络来完成的。稍后我们还将谈到这一点。

在点对点时代指导 WebSphere MQ 最佳实践发展的重要假设中,至少有两个假设在面向服务的体系结构中不再成立。这样的假设还有许多,但是有两个假设与这里的说明相关。它们分别是:

  • 队列管理器是名称解析的根。
  • 对象定义是相对静态的。

正如您在上面看到的,结果是几乎所有操作均为构建时操作,更改队列管理器名称干扰了对象名称解析,对消息路由做出更改需要重新配置物理网络。

SOA 范式

面向服务改变了所有这一切,使得消息网络更具有弹性、更加透明,并且更容易管理。或者,它至少可以潜在地更改消息网络的这些方面。为了获得好处,必须更新我们的某些最佳实践。当然,可以为面向服务而设计应用程序,但是却将它们部署到传统消息网络上,实际上大多数时候都是这样做的。

与本讨论相关的一些面向服务功能包括:

  • 位置独立性:这意味着目的地应该从网络中的任何位置可用。或者,放在前面讨论的上下文中来说,集群是用于名称解析而不是队列管理器的根容器。队列管理器的角色又后退到了队列和主题的匿名容器的角色。即使在我们考虑应答队列时也是如此。队列管理器名称需要完全限定应答消息的地址,但它是在运行时确定的,并且仅在应答消息的生存期中有效。这促使我们讨论:

  • 运行时名称解析:与物理地重新配置网络以更改路由不同,您可以使用 WebSphere MQ 集群功能实现相同的结果。基本拓扑是通过向集群广告各个对象而构建的,例如队列和别名。然后,日常的操作更改将通过启用或禁用集群中的那些对象或通过挂起或恢复队列管理器来执行。

这里的关键在于,为了将名称和路由解析从网络移动到 WebSphere MQ 集群要求,需要将适用于构建时的任务和属性与适用于运行时的任务和属性分离。它要求我们的工具和流程认识到网络现在具有状态,并且在做出更改时必须考虑到该状态。工具更改听起来似乎有很多工作要做。实际上并不是这样,不过在我们考虑这点之前,让我们看看它为我们带来了什么。

将名称解析向上移动到集群意味着路由不再与物理网络连接绑定在一起。集群提供了一个虚拟的网状网络,其中每个节点彼此相连,并且可以通过操作集群命名空间中的对象来控制其中的路由。当然,这样存在不必管理通道的优点,但是也就不过如此而已。在物理网络层控制路由需要将策略嵌入到拓扑中。这非常不灵活、非常有限制性,并创建了并不与其他方式相关的应用程序之间的依赖关系。在集群中控制路由可以支持任何数量的拓扑在相同物理网络上独立地共存,并且还使我们能够将集群命名空间与服务注册中心命名空间保持一致。提供和使用服务的应用程序将解析服务注册中心的名称,然后这些名称又在 WebSphere MQ 网络中进行解析。这些命名空间越是紧密地保持一致,在它们之间垂直移动名称解析时遇到的摩擦就越少。

返回到我们的用例,SOA 环境中的迁移、故障转移和扩展不再是差别非常大的流程,而是成为了现在的相同流程的次要变化形式。故障转移成为了所有三个流程的模板。存在一个构建时任务以创建备用环境,以及一个运行时任务以在主节点和辅助节点之间切换。迁移不过就是永不退回的故障转移,扩展是永远不将主节点置于离线的故障转移。运行这些流程的任何人现在只需学习一个具有少许次要变化的基本任务列表,从而产生更加一致的结果和更少的缺陷。此外,现在可以对单独的应用程序甚至单个资源进行故障转移,而以前的故障转移单位是整个队列管理器。面对走向合并的趋势,这将使得许多应用程序能够共享队列管理器。

SOA 实现

我在前面说过,更改工具不一定要付出很高的代价。主要要求在于,您的构建时工具要考虑到系统的运行时状态并且不任意地重置该状态。您仍然需要保留对象定义脚本,并且可能仍然能够在任何时候完整地运行它们以添加新对象。对对象定义进行很小的更改即可实现这些目标。所需的要求就是将构建时对象属性与运行时属性分离开来。例如,队列的运行时属性包括是否打开触发,以及当前是启用还是禁用了 PUT 和 GET。以前一个示例中的相同队列为例,对象定义脚本现在类似如下:

清单 3
DEFINE QLOCAL (APP.FUNCTION.SUBFUNCTION.QA) +
       GET(DISABLED) +
       PUT(DISABLED) +
       NOTRIGGER +
       NOREPLACE
ALTER  QLOCAL (APP.FUNCTION.SUBFUNCTION.QA) +
       DESCR('APP service queue for QA') +
       DEFPSIST(NO) +
       BOTHRESH(5) +
       BOQNAME('APP.FUNCTION.BACKOUT.QA') +
       CLUSTER('DIV_QA') +
       CLUSNL(' ') +
       DEFBIND(NOTFIXED)

所有视为运行时属性的属性放在带 NOREPLACE 选项的 DEFINE 语句中。该脚本的第一次执行将创建处于初始运行时状态的队列。该队列(根据该示例中的定义)有效地对集群隐藏,因为 GET 和 PUT 已经被禁用。现在可以使用所选的管理工具更新队列的 GET 和 PUT 状态,而不会导致该脚本将这些状态重置回初始状态的任何危险。由于 NOREPLACE 选项,该脚本的附加执行将简单地跳过运行时属性。下一个语句使用被视为构建时属性的属性来修改队列。此语句在该脚本每次运行时执行,如果需要永久地更改某个内容,就可以在此语句中进行。

您在前面看到,将名称解析向上移动到集群级别减少了队列管理器的任务。在新的范式中,队列管理器只是队列和主题的生命保障。实际的队列管理器名称对应用程序或服务注册中心来说变得不太重要了。事实上,如果继续提供对应用程序或服务注册中心有意义的队列管理器名称,它们最终将变为约束,将您锁定在特定的拓扑或部署模式中,剥夺了您希望通过采用 SOA 来获得的灵活性。在新模型中,对应用程序或注册中心有意义的名称(队列管理器别名、队列、主题)向上移动到逻辑层,其余名称(队列管理器、通道、集群)则下推到物理层。如果您使用 MQ 已有足够长的时间,也许记得最佳实践为按主机命名队列管理器的时代。这些年来,我们已偏离了该最佳实践,但是我建议的实现带我们绕了整个圈子,又回到了原来的最佳实践。在此模型中,按所在的主机命名队列管理器,并使用队列管理器别名来实现路由和对应用程序有意义的目的地。

将名称解析委托给集群并增强脚本以后,下面让我们看看用例的大致情况:

  • 迁移:此过程现在看起来像故障转移,但是不预期执行任何退回。现在存在截然不同的构建时和运行时任务。新的队列管理器在集群中构建、置于在线和挂起。通过禁用 PUT 和 GET 或者不设置 CLUSTER 或 CLUSNL 属性,从而在集群中定义和禁用队列。由于新的队列管理器可以与现有的队列管理器和平共存,因此可以在切换之前充分测试该部署。例如,可以安装应用程序和测试授权。切换的执行就像故障转移测试的第一部分。如果切换成功,旧的节点将退役。如果不成功,迁移看起来完全就像故障转移测试,因为退回技术取代了旧式的撤销计划。

  • 故障转移:故障转移的基本任务保持相同:将处理切换到辅助节点,然后再切换回去。区别在于,与通过修改 CONNAME 属性重新路由物理网络连接来执行此任务不同,路由是使用 WebSphere MQ 集群的功能来完成的。在大多数情况下,这意味着在辅助节点上启用队列,并在主节点上禁用它们。或者,可以使用队列管理器别名来建立一个或多个队列管理器作为目的地。在此情况下,故障转移将涉及到在辅助节点上启用别名,并在主节点上禁用它。任一种情况下的退回都涉及到逆向执行这些操作。无论所使用的模型如何,都可以作为脚本或通过管理工具实现操作。

  • 扩展:扩展是主节点保持在线的故障转移。向下扩展就像退回操作,其中没有将主节点置于在线的任务。

优点

剖析我们的用例,您可以看到它们现在全都由少数公共子任务组成:

  • 构建队列管理器并在集群中对其进行注册。
  • 在逻辑层创建路由条目。
  • 构建初始状态的队列和主题。
  • 启用节点。
  • 禁用节点。
  • 使队列管理器退役。

迁移按顺序差不多运行完这其中所有的任务。故障转移相继使用两次启用/禁用任务。向上扩展使用启用任务,向下扩展使用禁用任务。如果单独地列出这其中每个子任务,则为您的每个用例创建操作过程手册将非常简单,只需按正确的顺序组合子任务即可。是不是开始听起来有点熟悉了?重用、封装、流程组合:通过将名称解析委托给集群并增强工具以防止干扰集群的状态,您将拥有支持 SOA 的消息网络。

总结

当今可找到的大多数 WebSphere MQ 最佳实践文档都不会建议您将队列管理器名称与物理网络绑定在一起。如果您的确发现了这样的文档,它很可能是十年或更久以前的文档。大多数相同的文档都将包含示例对象定义脚本,但是其中没有哪个文档会演示我这里建议的 DEFINE/ALTER 技术。这是不是说这些文档错了?非也,它们在创建这些文档时非常流行的点对点消息模型的上下文中完全有效。但是如果您尝试在本质上为点对点的消息网络之上实现面向服务的体系结构,那么结果在最好的情况下是不灵活和难于管理,在最坏的情况下则是脆弱和不可靠的。

为了充分利用面向服务,需要在消息层中而不只是在其上的应用程序中对其进行实现。为此,需要重新评估您的既定最佳实践,以确保它们所依据的基本假设仍然成立。在本文的示例中,您更改了在物理层实现消息路由的假设和做法,并将其向上移动到了逻辑层中,并在那里由集群进行管理。这意味着集群现在具有运行时状态,因此您增强了自己的脚本工具以将状态考虑在内。这些细小的更改为最后的转换阶段提供了支持,该阶段将迁移、故障转移和扩展过程分解为可重用的原子任务,然后您可以将这些任务组合到组合工作流中。

明显的结果在于,三个用例变得彼此紧密相似,在此基础上预期可以减少培训需求和人为错误导致的缺陷。但是不太明显的方面是这些更改如何使得网络变得如此能力超群。通过在物理层之上的逻辑层中定义路由,可以在相同网络结构上实现许多重叠的拓扑。相对于工具更改的成本,单凭这一项就是物超所值的。通过移动应用程序的一个或多个实例来重新分布工作负载就变得微不足道了。所有的队列管理器——主节点、辅助节点、灾难恢复节点——全都可以同时在线。这将新队列管理器的构建和部署任务分离,并支持节点的早期测试和验证。由于这些技术在点对点模型中同样非常有效,因此可以在任一种类型的网络上加以实现。

但是最终,这只是新的需求和不断变化的环境如何打破现有的流程和最佳实践的一个例子。为了跟上潮流,需要偶尔重新检查一下我们的 MQ 工具和方法,并乐于接受变化。


相关主题


评论

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere, SOA and web services
ArticleID=379691
ArticleTitle=任务:消息: WebSphere MQ 集群中的迁移、故障转移和扩展
publish-date=04152009