websphere mq
关于IBM®WebSphere®MQ共享队列的优点,尤其是它们提供消息的连续可用性的能力,已有很多论述。 但是,在规划和实施过程中,出现了一些有关最佳使用共享队列及其对应用程序的影响的问题。 尽管有些问题是众所周知的,例如确保数据序列化所需的应用程序代码,但其他问题并未引起太多关注。 本文中的建议基于生产环境中的实现,并且通常包括所有WebSphere MQ应用程序的最佳实践。 除非应用程序也健壮和高度可用,否则使基础结构变得健壮和高度可用的努力收效甚微,因此,应用程序最佳实践对于共享队列实现的成功也至关重要。
本文不涉及某些共享队列主题。 WebSphere MQ V6的一项新功能允许共享队列中的消息大于63K,但是不包括这些消息对应用程序和资源利用的影响,因为在撰写本文时,WebSphere MQ V6尚未在任何生产环境中实现。 此外,共享通道和组内排队也不包括在内。
本文中使用的示例应用程序称为PTR。 它的预期消息量为每天1,000,000条消息(峰值速率将在后面讨论),包括消息描述符(MQMD)的平均消息大小为3.5K。 消息分布在两个队列中,它们之间的音量平均分配。 消息将由称为PTRC的CICS事务处理。
与专用队列不同,专用队列的大小受页面集大小的限制(最大4G或64G,取决于WebSphere MQ的版本),而共享队列则受应用程序列表结构大小的限制。 该结构是在耦合设备(CF)中分配的存储区域。 CF是一种公共资源,由sysplex本身使用:DB2,CICS,IMS和其他WebSphere MQ结构。 结构大小由z / OS系统管理员通过IXCMIAPU设置。 每个WebSphere MQ队列共享组(QSG)至少需要两个结构,一个用于管理,一个或多个应用程序结构。
实际上,大多数队列共享组都是用管理结构和至少两个应用程序结构定义的,一个用于持久性消息,一个用于非持久性消息。 WebSphere MQ管理员需要知道是否可以将持久性消息放入共享队列。 必须在持久列表结构中定义可以同时包含持久消息和非持久消息的队列。
CF施加的大小限制使一些客户质疑他们的高容量应用程序是否适合共享队列。 在某些情况下,CF容量确实禁止使用共享队列,例如在批处理作业中,成千上万的消息在队列中保留了较长时间。 但是在大多数情况下,此问题被高估了,而实际上如何使用队列(例如,消息通常在队列中保留多长时间)对于确定使用共享队列是否合适更为重要。
WebSphere MQ提供的样本应用程序结构的初始大小设置为266 MB,最大大小为512 MB。 本节说明如何计算可以将多少个PTR消息放入定义的结构中。
应与应用程序组进行讨论,以确定高峰期预期的最大深度,消息的大小以及队列中的预期持续时间。 在知道消息处理速率并且实际客户正在使用该系统之前,进行这些估计可能很困难。 但是,与任何容量规划工作一样,您需要一个基准。
假设应用程序开发人员请求足够的存储空间,以将一天中预计的消息数量的20%保留在队列中,以在消息可能泛滥到系统中或拉动事务无法跟上消息的高峰时段。请求数。 此行为是一个例外,通常仅在网络或应用程序中断期间才会发生。 仅保存PTR消息所需的CF结构大小为:
注意: 30%的间接费用津贴是基于耦合设施控制代码(CFCC)级别12的观察得出的。如果您处于不同的CFCC级别,则该值可能会有所不同。 有关更多信息,请参阅WebSphere MQ SupportPac MP16:WebSphere MQ for z / OS的容量规划和调整 。
889 MB的要求可能不现实。 实际上,它大于WebSphere MQ V5.3定义的缺省应用程序结构大小。 与z / OS系统程序员讨论时,它的响应也会引起笑声。 如果该值太高,那么每天预期邮件流量的5%大约是多少? 如果1,000,000 MPD速率相当均匀,那将比一小时的消息价值略多。 计算如下:
该值也可能不现实,因为它将占用几乎整个初始结构的大小。 如果PTR队列已满,则结构中定义了队列的其他应用程序可能会受到影响。
最小需求量的1%可能是唯一可行的选择:
定义请求队列时,将最大消息数保持为调整结构大小时使用的消息数。 z / OS上的缺省队列深度(MAXDEPTH)是999,999,999条消息。 尽管在达到此限制之前会遇到结构/存储介质已满的情况,但重要的是要记住,除非受队列深度限制,否则在一个队列上建立的消息可能会使用整个应用程序结构。 填充结构将影响在该结构中定义了队列的所有其他应用程序。
要定义请求队列以容纳预期数量的1%,定义应如下所示:
DEFINE QLOCAL('PRTA.REQUEST') CMDSCOPE(' ' ) QSGDISP(SHARED)
REPLACE
DEFPSIST(YES)
BOQNAME('PRT.REQUEST.BOQ' )
BOTHRESH(3)
CFSTRUCT(QSG1PERS)
HARDENBO
MAXDEPTH(5000)
QDEPTHHI(80)
QDEPTHLO(40)
QDPHIEV(ENABLED)
QDPLOEV(ENABLED)
QDPMAXEV(DISABLED)
DEFINE QLOCAL('PRTB.REQUEST') CMDSCOPE(' ' ) QSGDISP(SHARED)
REPLACE
DEFPSIST(YES)
BOQNAME('PRT.REQUEST.BOQ' )
BOTHRESH(3)
CFSTRUCT(QSG1PERS)
HARDENBO
MAXDEPTH(5000)
QDEPTHHI(80)
QDEPTHLO(40)
QDPHIEV(ENABLED)
QDPLOEV(ENABLED)
QDPMAXEV(DISABLED)
在上面的示例中,定义的队列最多占用该结构的45 MB。 如果在结构中需要定义其他应用程序队列,请对它们进行相同的大小调整。
将队列添加到应用程序结构时的另一个注意事项是重叠高峰时间。 例如,如果有两个队列可能需要多达45MB的存储空间,而结构只有64MB,那么如果它们的峰值处理时间不重叠,或者队列深度从不接近,则可能永远不会遇到结构或队列已满的情况。最大值。
即使消息量很大,共享队列也可以在大多数应用程序中很好地工作。 真正的限制因素不是通过队列的消息数,而是通常可以到达队列的深度-这应该是一个很小的数字。 对于大容量应用程序,服务器进程必须具有高可用性,并能够快速从队列中提取消息。
当您评估队列深度要求时,消息处理速率与峰值消息量一样重要。 您可以通过检查系统管理工具(SMF)队列记帐记录(SMF116)来确定消息量和处理速率。 如果记录不可用,并且许多客户没有在生产环境中打开该级别的报告,则可以基于统计记录(SMF115),来自应用程序的审核日志,驱动的平均数据库操作数来估计数量和费率通过消息或其他应用程序指示符。
另一个估算工具是RESET QSTATS命令。 如果在正常的生产或测试周期内定期发布,则可以捕获并跟踪在该间隔内和队列深度较高时已处理的消息数。
如果这是一个新应用程序,或者无法计算消息速率,则必须从测试过程中生成的SMF数据估计并得出消息量和处理速率。 进行这些估算时,不要假设消息全天均匀分布。 在可预测的高峰时段(例如正常工作时间),许多类型的请求要高得多。 每天的周期可能有多个高峰,就像在金融业中一样,在市场开盘之后和休市之前,通常都有主要的高峰。 其他高峰时段可能不取决于日常周期,而可能与月末,年末,节假日前的时段或促销活动或故障转移等不可预测的流量高峰有关。
与您的应用程序开发团队讨论消息流量的预期分布,然后在生产前测试期间测试和评估峰值处理速率。 然后,请确保在应用程序投入生产后,监视消息流量,尤其是在共享队列上。
作为每日峰值消息速率的示例,如果我们假设在8个小时内有75%的预期1,000,000条消息进入,则在此期间,消息流量平均每秒将有26条消息到达请求队列。 如果高峰时段较短,或者在高峰时段内有较高百分比的消息进入,则每秒的消息量当然会增加。 为了保持较低的队列深度,服务器进程必须以更高的速率运行。
在下面的示例中,消息放入速度是获取速度的两倍,并且您可以看到队列深度Swift增加。 2:1的速率差异是为了简化-每个应用程序都会有所不同,并且速率通常会随时间而变化。 服务应用程序比请求应用程序慢的模式是正常的,因为典型的服务器应用程序要做的工作是:读取表,进行计算,更新行等。
在生产前测试中,您应该确定看跌和收看率。 虽然这些速率可能与您在生产中看到的速率不匹配,但是它们应该为您提供一个起点,以确定必须运行多少个服务应用程序才能跟上请求的应用程序。
显然,如果此应用程序有0.5秒的响应时间服务级别协议,则将很快违反该协议。 并且,如果将队列深度设置为先前计算的5000,则在前半小时内会超过该深度。 有许多技术可以纠正这种情况,下面介绍一些更常见的技术。
如果没有阻止程序运行服务器应用程序的多个副本,则对服务器应用程序以比请求应用程序慢的速度处理消息的最简单解决方案是运行服务器程序的多个副本。 在这个简单的示例中,仅需要服务器应用程序的两个副本。 实际上,应用程序的多个副本通常不会以相同的速率运行,因此需要进行应用程序测试和评估才能确定实际速率。
在我们的简单示例中,由于服务器进程是CICS事务,因此简单地在多个CICS区域中运行服务器事务的多个副本将使队列深度非常低。 类似的技术可以用于IMS事务。 其他进程(批处理,应用程序服务器等)需要更多的考虑,但是有使用几乎所有正在使用的进程模型的共享队列的示例。
具有足够的处理事务,足够的执行MQGET的程序,可以在不违反SLA或不超过容量的情况下共享此大容量队列。
另一个常见的考虑因素是数据序列化。 如果必须按严格的顺序处理消息,则只能有一个放置和获取应用程序,这通常需要调整队列的大小以容纳更多消息。 有关确保序列化的应用程序编码的更多信息,请参阅《 IBM Redbook 并行Sysplex应用程序注意事项(SG24-6523)》 。
序列化要求及其影响并非WebSphere MQ处理所独有。 但这通常被认为是一个问题,尤其是当基于文件的批处理被替换为可以从多个位置启动的实时处理时。 从数据可用性的角度来看,应尽可能消除序列化要求。 如果无法消除或在短期内无法消除,则可以使用目标序列化的简单技术来帮助管理序列化需求。
减少数据序列化要求影响的一种简单方法是查看它是否适用于数据的逻辑子集。 例如,在许多情况下,仅在特定帐户或物料编号内才需要数据序列化。 在这种情况下,发出请求的应用程序可以将消息分类到队列中,这些队列保存序列化数据的定义范围。 每个请求队列将只有一个服务应用程序以确保序列化,但是总工作量并不局限于一个服务器进程。 如上面所示的多服务器示例中所示,可以避免队列建立。
目标序列化的示例如下所示:
这将要求应用程序打开多个队列,应用分发逻辑,等等。 另外,随着消息量的增长,可能必须更改应用程序才能打开更多队列。
如果应用程序正在生产中并且无法进行更改,或者消息从多个源中流出,那么使用WebSphere Message Broker或定制应用程序可以提供类似的功能。 添加此处理的开销通常远小于一个大批量序列化过程的影响。 一个例子如下所示:
该模型的优点是,随着消息量的增长,添加新队列不需要更改请求的应用程序。 同样,如果分发模式随时间而变化,则在规则驱动的引擎中更改分发消息的标准比在分布式应用程序中更容易。
某些序列化要求不是由必须顺序处理消息的要求所驱动,而是由各个消息之间的亲和力所驱动。 通常,消息是逻辑关联的,例如当多个消息组成一个应用程序事务时,或者是基于类型排序的消息,例如,只有在接受初始订单后才能处理更改或取消的消息。
从应用程序编码的角度来看,要求对所有消息或记录进行序列化通常比对亲和性进行编码更容易。 这项要求可能是来自面向文件的批处理的后遗症,在此过程中,它很简单,可以确保信息以预定的顺序进入流程。
消息亲缘关系可能紧密或松散。 紧密关联是指必须一起处理几条消息以完成逻辑交易(例如在采购订单中),通常由标头信息,一个或多个订单项和预告片信息组成。 松散关系通常是修改请求,只有在原始交易完成后才能进行处理。 例如,仅在原始交易完成后才能处理订单修改或取消信用卡费用。
为了获得紧密的消息亲和力,WebSphere MQ提供了消息分组,以将多个消息作为一个逻辑事务逻辑地绑定在一起。 从应用程序角度看,推杆应用程序必须:
正在获取的应用程序必须:
在某些应用程序中,只有一小部分消息需要序列化。 典型示例是订单取消必须在初始订单之后到达的情况。 如果多个服务器从共享队列中获取,则可能会不按顺序检索消息。 应用程序设计者可能会决定包括处理这些无序情况的逻辑,如以下伪代码示例所示:
IF a message cannot be processed because it is out of sequence
(e.g. an order change precedes an order create request:
THEN DO
DELAY for a small time (typically a few milliseconds)
ROLLBACK the transaction (increments MQMD.BackoutCount)
END
我们假设MQGET处理已经包括对Backout Count的检查(请参阅下面的Backout讨论)。 延迟允许消息被撤消之前的消息有时间到达。 仅当消息的很小子集(通常是成对)需要排序时,此技术才有效。
即使是专用队列,有时也会不时填满,通常是在网络中断时间较长的情况下。 一些客户发现,由于CF施加的大小限制更加严格,共享队列可能更容易填充。 放置应用程序应解释以下返回代码并采取适当的措施:
MQRC_Q_FULL (2053, X'805') Queue already contains maximum number of messages
MQRC_STORAGE_MEDIUM_FULL (2192, X'890') External storage medium is full
(also known as MQRC_PAGESET_FULL)
MQRC_CF_STRUC_FAILED (2373, X'945') Coupling-facility structure failed.
MQRC_CF_STRUC_IN_USE (2346, X'92A') Coupling-facility structure in use.
适当的操作取决于应用程序和环境。 一些应用程序操作包括:
在示例队列定义中,包含了回退信息,如下所示。
DEFINE QLOCAL('PRT.REQUEST') CMDSCOPE(' ' ) QSGDISP(SHARED)
REPLACE
DEFPSIST(YES)
BOQNAME('PRT.REQUEST.BOQ' )
BOTHRESH(3)
CFSTRUCT(MQM1DIVS)
HARDENBO
MAXDEPTH(10000)
QDEPTHHI(80)
QDEPTHLO(40)
QDPHIEV(ENABLED)
QDPLOEV(ENABLED)
QDPMAXEV(DISABLED)
MQ管理员设置回退参数时,行为良好的WebSphere MQ应用程序实际上会使用它们来从队列中除去潜在的“中毒”消息,或者由于其他问题而无法处理的消息。 尽管症状可能有所不同,但这对于共享队列和专用队列都非常重要。 参数为:
如果无法处理专用队列上的消息并发出回滚,则该消息将返回到队列顶部。 该队列的下一个MQGET将提取问题消息并尝试再次对其进行处理。 如果该尝试失败并且事务被回滚,则消息再次到达队列顶部。 WebSphere MQ维护一个回退计数,当应用程序在同一条消息上循环时,该通知可以通知该应用程序。 如果应用程序忽略了退出计数器,则毒气消息的第一个指示是队列深度开始上升,并且获取进程继续运行。
在共享队列上,当有多个服务器进程在运行时,队列深度可能不会急剧增加,因为在处理有毒消息时,会从队列中拾取和处理其他消息。 仅有一个流氓消息,不断重复处理-耗尽CPU周期,但不停止工作。
在某些情况下,回退一条消息并允许进行几次处理是合理的。 例如,如果数据库行或表不可用,则下次处理该消息时它可能变得可用。
行为良好的应用程序将在读取的每个消息中检查回退计数,如果该计数不为零,则将其与队列中定义的回退阈值进行比较。 如果计数大于阈值,则应将消息写入BOQNAME参数中指定的队列中并提交。 通常,在邮件上附加一个死信头(MQDLH),以指示为什么将邮件写入回退队列。
某些应用程序对某些服务类别有很高的可用性要求。 首要客户或具有较高经济价值的请求可能需要共享队列提供的连续可用性,而其他消息流量不能保证该服务水平。 就像上面显示的“目标序列化”示例中一样,您可以使用应用程序或代理工具将所选消息路由到共享队列,将其他消息路由到私有队列(可能定义为集群的一部分)。
有时,共享队列不能满足可用性需求。 对于这些应用程序,WebSphere MQ集群通常可以提供比点对点实现更高级别的可用性。 此外,您可以使用标准故障转移技术来就地或在其他LPAR上重新启动队列管理器。
正如我曾祖母经常说的那样:“许多双手使轻巧工作。” 许多人贡献了经验,帮助完善了想法,检查了我的数学,纠正了错别字,并修复了不稳定的语法。 特别感谢Emir Garza,Bob Herbison,Mark Taylor和Steve Zehner。
翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/0512_elkins/0512_elkins.html
websphere mq