![]() | |
Sun Java System Message Queue 3.5 SP1 管理指南 |
第 9 章
分析和调整消息服务本章包括大量有关如何分析和调整 Message Queue 服务以优化消息传送应用程序性能的主题。包括下列主题:
关于性能性能调整过程
您的消息传送应用程序的性能取决于该应用程序与 Message Queue 服务之间的交互。因此,若要获得最佳性能,则需要应用程序开发者和管理员的共同努力。
优化性能的过程从应用程序设计开始,一直持续到部署应用程序之后对消息服务的调整阶段。性能调整过程包括下列阶段:
上述过程常常需要反复进行。在应用程序的部署过程中,Message Queue 管理员应该评估消息服务器是否适用于应用程序的总体性能要求。如果基准检验测试符合这些要求,管理员就可以按本章中所述调整系统。但是,如果基准检验测试不符合性能要求,则可能需要重新设计应用程序或者修改部署体系结构。
性能方面
通常,性能是对消息服务将消息从生成方传送到使用方时的速度和效率的一种衡量。但是,取决于您的需要,可能会有几个不同的性能方面对您特别重要。
连接负荷 系统所能支持的消息生成方、消息使用方或并行连接的数量。
消息吞吐量 每秒钟能通过消息传送系统抽取的消息数或消息字节数。
稳定性 消息服务的总体可用性,或者当负荷较重或发生故障时性能的下降程度。
效率 消息的传送效率,这是一种与使用的计算资源相关的消息吞吐量的衡量。
这些不同的性能方面总而言之是相辅相成的。如果消息吞吐量很高,则意味着消息在消息服务器上作为待办事项累积的可能性就会变小,因此延迟时间也应该较低(单条消息可以很快地传送)。但是,延迟可能取决于许多因素:通信链接的速度、消息服务器的处理速度和客户机的处理速度,以及其他众多方面。
在任何情况下,性能都有几个不同方面。哪些方面对您最重要?这通常要取决于特定应用程序的要求。
基准检验
基准检验是为消息传送应用程序创建测试套件,并针对此测试套件衡量消息吞吐量或其他性能方面的一种过程。
例如,您可以创建这样一个测试套件:一定数量的生成方客户机使用一定数量的连接、会话和消息生成器,将标准大小的持久性或非持久性消息按照某个特定速率发送至队列或主题(这完全取决于消息传送应用程序的设计)。同样,测试套件中还包括一定数量的使用方客户机,它们使用一定数量的连接、会话和特定类型的消息使用器(通过特定的确认模式来使用测试套件的目标中的消息)。
使用标准的测试套件可以衡量消息的生成和使用之间所花的时间或者消息的平均吞吐速率,您还可以监视系统以观察连接线程使用情况、消息存储数据、消息流数据以及其他相关度量依据。这样就可以提高消息的生成速率、消息生成方的数量或者其他变量,直到性能受到负面影响为止。可能达到的最大吞吐量就是消息服务配置的基准。
使用此基准可以修改测试套件的某些特征。控制所有可能影响性能的因素时请小心(请参见“影响性能的应用程序设计因素”),您可以记录这些因素导致基准发生了哪些变化。例如,您可以将连接数或消息大小增加五倍或十倍,并记下对性能产生的影响。
相反,您也可以将基于应用程序的因素保持不变,而以某种控制方式更改代理配置(例如,更改连接属性、线程池属性、JVM 内存限制、限制行为、内置与插入的持久性等),并记下这些更改如何影响性能。
当您需要通过调整消息服务来增加所部署的应用程序的性能时,这种应用程序基准检验可以提供非常有价值的信息。基准检验可用于更准确地预测所作的更改或一系列更改产生的影响。
通常,基准检验应该在受控制的测试环境下运行,并且运行足够长的时间,以使消息服务能够稳定。(性能在启动时会受到实时编译的负面影响,因为要将 Java 代码转换为机器代码。)
基线使用模式
部署并运行消息传送应用程序后,建立基线使用模式是很重要的。您需要知道何时发生峰值需求,并且需要能够量化该需求。例如,需求通常会随最终用户的数量、活动级别、一天当中的时间,或者以上所有这些因素而发生波动。
要建立基线使用模式,您需要在一段较长的时间内监视消息服务器,并查看下列数据:连接数、存储在代理(或特定目标)中的消息数、流入和流出代理(或特定目标)的消息,以及活动的用户数目等等。还可以使用度量依据数据中提供的平均值和峰值。
将这些基线度量依据数据与设计时的期望值进行比较是非常重要的。通过执行此操作,可以检查客户机代码是否运转正常:例如,检查连接是否未保持打开或者已使用的消息是否仍然保留在未确认状态。这些编码错误会消耗消息服务器资源,并可能极大地影响性能。
基线使用模式有助于确定如何调整系统以优化性能。例如,如果某个目标的使用频率明显高于其他目标,那么您可能需要对该目标设置比其他目标更高的内存限制,或者相应地调整限制行为。如果需要的连接数明显大于允许的最大线程池大小,那么可能需要增大线程池的大小,或者采用共享线程模型。如果峰值消息流远远大于平均消息流,这可能影响您在内存不足时采用的限制行为。
通常,您对使用模式了解得越多,就能越好地将系统调整为这些模式。并计划将来的需要。
影响性能的因素消息延迟和消息吞吐量是两个主要的性能指示器,它们通常取决于典型消息在完成消息传送过程中的各个步骤时所需的时间。下面步骤显示了如何以持久、可靠的方式传送消息。这些步骤将在插图之后讲述。
图 9-1 通过 Message Queue 服务传送消息
由于这些步骤是连续的,所以它们中的任何一个都可能成为消息从生成方客户机到使用方客户机的传送过程中的瓶颈。这些步骤中的大多数都取决于消息传送系统的物理特征:网络带宽、计算机处理速度和消息服务器体系结构等等。但是,有一些步骤还取决于消息传送应用程序的特征和该应用程序要求的可靠性级别。
以下各小节讨论应用程序设计因素和消息传送系统因素这二者对性能的影响。尽管应用程序设计和消息传送系统因素在消息的传送过程中交互紧密,但它们彼此是独立的。
影响性能的应用程序设计因素
应用程序的设计决策对消息传送的总体性能有很大影响。
对性能影响最大的主要是那些影响消息传送的可靠性因素。包括下列因素:
其他影响性能的应用程序设计因素有:
接下来的几节讲述这些因素当中的每一个对消息传送性能所产生的影响。通常,性能和可靠性应该折衷。增加可靠性的因素可能会导致性能降低。
下表显示各个应用程序设计因素大体上如何影响消息传送性能。该表显示了两个方案(一个高可靠性、低性能方案和一个高性能、低可靠性方案)和分别相应于这两个方案的应用程序设计因素选项。在这两种极端情况之间,有很多可以同时影响可靠性和性能的选项和折衷。
注意
在接下来的图中,性能数据是在一个使用基于文件的持久性双 CPU、1002 Mhz Solaris 8 系统上生成的。性能测试首先预热 Message Queue 代理,使实时编译器优化系统,并启动持久性数据库。
代理预热后,会创建单个生成方和单个使用方,并在 30 秒钟内生成消息。系统将记录使用方接收所有生成的消息所需的时间,并计算吞吐率(每秒收到的消息数)。对于表 9-1 中所示的不同应用程序设计因素组合,此情形会重复出现。
传送模式(持久性/非持久性消息)
如“可靠消息传送”中所述,持久性消息能够在消息服务器发生故障的情况下保证消息的传送。代理会把消息存储在持久性存储库中,直到所有预期的使用方都确认已使用消息为止。
通过代理处理持久性消息比处理非持久性消息要慢,理由如下:
持久性和非持久性模式的性能之间可以有很大的差别。图 9-2 比较了在两种可靠的传送情况下持久性和非持久性消息的吞吐量:同时将 10k 大小的消息传送至队列和长期订阅的主题。两种情况下都使用 AUTO_ACKNOWLEDGE 确认模式。
图 9-2 传送模式的性能影响
使用事务
事务是一种保证,保证在事务会话中生成和使用的所有消息将作为一个单元进行处理或不进行处理(回滚)。
Message Queue 同时支持本地和分布式事务(有关详细信息,请分别参见“本地事务”和“分布式事务”)。
消息在事务会话中生成或确认时比在非事务会话中要慢,理由如下:
确认模式
确保可靠传送 JMS 消息的一种机制是,客户机确认使用了由 Message Queue 消息服务器传送给它的消息(请参见“可靠传送:确认和事务”)。
如果在客户机尚未确认消息之前就关闭了会话,或者如果消息服务器在处理确认之前发生了故障,代理将重新传送该消息,并设置一个 JMSRedelivered 标志。
对于非事务会话,客户机可以选择三种确认模式之一,这三种模式有其各自的性能特征:
(CLIENT_ACKNOWLEDGE 模式的用法与事务的用法类似,不同之处在于:它不能保证当提供者在处理过程中发生故障时,所有确认都将一起处理)。
确认模式可以影响性能的理由如下:
长期与非长期订阅
主题目标的订阅者可以归为两类,即长期订阅和非长期订阅的订阅者,如“发布/订阅(主题目标)”中所述:
长期订阅的可靠性较高,但代价是吞吐较慢,原因如下:
图 9-3 比较了两种情况下的长期订阅和非长期订阅主题目标的吞吐量:10K 大小的持久性和非持久性消息。两种情况下都使用 AUTO_ACKNOWLEDGE 确认模式。
从图 9-3 中可以看到只有在持久性消息情况下,使用长期订阅的性能影响才会很明显,出现这种影响是因为持久性消息只有在长期订阅时才会永久存储,如上文所述。
图 9-3 订阅类型的性能影响
使用选择器(消息过滤)
应用程序的开发者常常需要将消息组的目标定为特定使用方。实现此愿望的方法有两种:将每组消息分别指向唯一的目标;或者是仅使用单个目标,并为每个使用方注册一个或多个选择器。
选择器是一种只请求特定消息的字符串,这些消息的属性值(请参见“JMS 消息结构”)应该与传送到特定使用方的字符串匹配。例如,选择器 NumberOfOrders 1 仅传送 NumberOfOrders 属性值为 2 或更大值的消息。
将使用方注册到选择器会降低性能(与使用多个目标相比),因为会需要进行额外的处理,以处理每个消息。如果使用选择器,则必须对它进行解析,以使它与将来的消息匹配。另外,路由每个消息时,都必须检索该消息的属性,并与选择器相比较。但是,使用选择器为消息传送应用程序提供了更大的灵活性。
消息大小
消息大小会影响性能是因为从生成方客户机到代理以及从代理到使用方客户机之间必须传递更多的数据,并且对于持久性消息,必须存储更大的消息。
但是,通过将较小的消息成批地变为一个消息,对各个消息的路由和处理就可以变得尽可能地简单,从而获得总体性能的提高。此时,就会丢失有关各个消息的状态的信息。
图 9-4 比较了在两种情况下,1k、10k 和 100k 大小的消息的吞吐量(KB/秒):持久性和非持久性消息。每种情况都将消息发送至队列目标,并使用 AUTO_ACKNOWLEDGE 确认模式。
图 9-4 显示在这两种情况下,传送较大消息的开销都比传送较小消息时要少。您还可以看到在 1k 和 10k 大小的消息上出现的情况:非持久性消息较持久性消息接近 50% 的性能提高在 100k 大小的消息上并未得到体现,可能是因为在这种情况下,网络带宽已经成为消息吞吐量的瓶颈。
图 9-4 消息大小的性能影响
消息主体类型
JMS 支持五种消息主体类型,按照复杂性顺序大致显示如下:
尽管通常情况下消息类型是由应用程序的需要所决定的,但较复杂的类型(MapMessage 和 ObjectMessage)会增加性能成本 对数据进行序列化和反序列化的成本。性能成本取决于数据的简单或复杂程度。
影响性能的消息服务因素
消息传送应用程序的性能不但受应用程序设计的影响,而且还受执行消息路由和传送的消息服务的影响。
以下各节讨论影响性能的各个消息服务因素。了解这些因素的影响对于评估消息服务以及诊断并解决在部署的应用程序中可能发生的性能瓶颈来说至关重要。
Message Queue 服务中影响性能的最重要的因素有:
以下各节讲述这些因素中的每一个对消息传送性能所产生的影响。
硬件
对于 Message Queue 消息服务器和客户机应用程序而言,CPU 处理速度和可用内存都是消息服务性能的主要决定因素。大多数软件限制都可以通过增加处理能力来消除,而添加内存则可以同时提高处理速度和容量。但是,仅通过升级硬件来克服瓶颈通常过于昂贵。
操作系统
由于不同操作系统的效率不同,所以即使硬件平台相同,性能也会各不相同。例如,操作系统使用的线程模型会对消息服务器可以支持的并行连接数产生重要影响。在所有硬件都相同的情况下,Solaris 通常比 Linux 快,而后者通常又比 Windows 快。
Java 虚拟机 (JVM)
消息服务器是受主机 JVM 支持并运行在其中的一种 Java 进程。因此,JVM 处理是决定消息服务器路由和传送消息的速度和效率的重要因素。
特别是 JVM 的内存资源管理至关重要。必须为 JVM 分配足够的内存以满足不断增大的内存负荷。另外,JVM 将定期地释放未使用的内存,而这种内存释放会延迟消息的处理。JVM 内存堆越大,内存释放过程中可能遇到的延迟就越长。
连接
客户机和代理之间的连接数目和速度可能影响消息服务器可以处理的消息数以及消息的传送速度。
消息服务器连接限制
对消息服务器的所有访问都是通过连接的方式进行的。对并行连接数的任何限制都会影响可以同时使用消息服务器的生成方或使用方客户机的数目。
消息服务器的连接数通常由可用的线程数限制。Message Queue 使用了线程池管理器,您可以将其配置为支持专用线程模型或共享线程模型(请参见“线程池管理器”)。专用线程模型的速度非常快,因为每个连接都有专用的线程,但是连接数目受可用线程数的限制(每个连接都有一个输入线程和一个输出线程)。共享线程模型对连接数不加任何限制,但是在大量连接之间共享线程时会有明显的开销和吞吐量延迟,特别是当这些连接都很繁忙时。
传输协议
Message Queue 软件允许客户机使用各种低级别的传输协议与消息服务器进行通信。Message Queue 支持“连接服务支持”中所示的连接服务(及相应协议)。协议的选择基于应用程序的要求(加密、通过防火墙访问等),但是所作的选择会影响总体性能。
图 9-5 传输协议速度
图 9-5 反映不同协议技术的性能特征:
消息服务器体系结构
Message Queue 消息服务器可以作为单个代理实现,也可以作为多个互相连接的代理实例(即代理群集)实现。
随着连接到代理的客户机数量以及所传送的消息数量的不断增加,代理最终将超出资源限制(例如文件描述符、线程和内存限制)。适应不断增加的负荷的方法之一是将更多的代理实例添加到 Message Queue 消息服务器,从而将客户机连接以及消息路由和传送分布到多个代理。
通常,如果客户机(特别是消息生成方客户机)均匀地分布在群集中,则这种调整最为有效。由于在群集的代理之间传送消息会涉及到开销,因此连接数有限或消息传送速率有限的群集,其性能可能会比单个代理要低。
您也可以使用代理群集来优化网络带宽。例如,您可能希望在群集内的一组远程代理之间使用低速的长途网络链路,而在客户机与其各自的代理实例之间使用高速链接进行连接。
有关群集的详细信息,请参见“多代理群集(企业版)”和“使用群集(企业版)”。
代理限制和行为
消息服务器可能需要处理的消息吞吐量是消息服务器所支持的消息传送应用程序的使用模式的一项功能。但是,消息服务器在资源方面有限:内存、CPU 周期等。因此,在消息服务器变得无响应或不稳定的位置,它可能会崩溃。
Message Queue 消息服务器具有管理内存资源并防止代理用尽内存的内置机制。这些机制包括可配置的消息数限制,或代理可以拥有的消息字节数或其各自的目标,以及当达到目标限制时可以实施的一组行为(请参见“管理内存资源和消息流”)。
通过仔细地监视和调整,这些可配置机制可以用于平衡消息的内流和外流,以使系统过载不会发生。尽管这些机制会造成开销并限制消息的吞吐量,但它们可以维护操作的完成性。
数据存储性能
Message Queue 既支持内置的持久性,也支持插入的持久性(请参见“持久性管理器”)。内置的持久性是基于文件的数据存储。插入的持久性使用 Java 数据库连接 (JDBC) 接口,并需要 JDBC 兼容的数据存储。
内置的持久性明显比插入的持久性要快,但是 JDBC 兼容的数据库系统可以提供应用程序需要的冗余、安全性和管理功能。
如果是内置持久性,您可以通过指定让持久性操作将内存中状态与数据存储同步,从而将可靠性增至最大。这有助于消除因系统崩溃而导致的数据丢失,但代价是性能的下降。
客户机运行时配置
Message Queue 客户机运行时可提供客户机应用程序及其与 Message Queue 消息服务的接口。它支持客户机向目标发送消息以及接收来自这些目标的消息所需的所有操作。客户机运行时是可配置的(通过设置连接工厂属性值),使您可以设置通常能够提高性能和消息吞吐量的属性和行为。
例如,Message Queue 客户机运行时支持下列可配置行为:
- 连接流测量 (imqConnectionFlowCount),此行为有助于防止由于 JMS 消息和 Message Queue 控制消息通过同一连接时所形成的流引起的拥塞。
- 连接流限制 (imqConnectionFlowLimit),此行为有助于通过限制等待使用的、可以通过连接传送到客户机运行时的消息数,来避免客户机的资源限制。
- 用户流限制 (imqConsumerFlowLimit),此行为有助于改进在多用户队列传送情况下用户之间的负荷平衡(因此向任何一个用户发送的消息数都是均衡的),并有助于阻止连接上的任何一个用户影响连接上的其他用户。此属性可以限制每个用户等待使用的、可以通过连接传送到客户机运行时的消息数。还可以将该属性配置为队列目标属性 (consumerFlowLimit)。
有关这些行为和用来配置这些行为的属性的详细信息,请参见“客户机运行时消息流调整”。
监视消息服务器Message Queue 服务器经配置后可以提供能够用于监视其性能的度量依据信息。本节描述可以用于监视消息服务器的各种工具以及能够使用这些工具获得的度量依据数据。
有关如何使用度量依据数据来解决性能问题或者分析和调整消息服务器性能的信息,请参见“性能问题疑难解答”。
监视工具
可以使用下列工具获得度量依据信息:
以下各节描述如何使用这些工具中的每一种以获得度量依据信息。有关不同工具之间的比较,请参见“选择适当的监视工具”。
Message Queue 命令行实用程序 (imqcmd)
命令行实用程序 (imqcmd) 是 Message Queue 的基本命令行管理工具。通过它可以管理代理及其连接服务,以及应用程序特有的资源,例如物理目标、长期订阅和事务。imqcmd 命令在第 6 章“代理和应用程序管理”中有所说明
imqcmd 命令的功能之一是它为作为一个整体的代理、为单个的连接服务以及为单个的目标获得度量依据信息的能力。要获得度量依据数据,通常应该使用 imqcmd 的 metrics 子命令。度量依据数据将按照您指定的时间间隔或者次数写到控制台屏幕上。
您也可以使用 query 子命令(请参见"imqcmd query")获得度量依据数据的更具体的子集。
imqcmd metrics
imqcmd metrics 的语法和选项分别如表 9-2 和表 9-3所示。
过程:使用 metrics 子命令显示度量依据数据
本节讲述使用 metrics 子命令报告度量依据信息的过程。
要使用 metrics 子命令,请执行下列操作:
度量依据输出:imqcmd metrics
本节显示代理范围、连接服务和目标度量依据的 metrics 子命令输出示例。
代理范围度量依据。 要获取在 10 秒的时间间隔内流入和流出代理的消息和数据包的速率,请使用 metrics bkr 子命令:
imqcmd metrics bkr -m rts -int 10 -u admin -p admin
此命令产生的输出结果类似如下内容(请参见表 9-8 中的数据说明):
连接服务度量依据。 要获取 jms 连接服务所处理的消息和数据包的累计总数,请使用 metrics svc 子命令:
imqcmd metrics svc -n jms -m ttl -u admin -p admin
此命令产生的输出结果类似如下内容(请参见表 9-9 中的数据说明):
-------------------------------------------------
Msgs Msg Bytes Pkts Pkt Bytes
In Out In Out In Out In Out
-------------------------------------------------
164 100 120704 73600 282 383 135967 102127
657 100 483552 73600 775 876 498815 149948
目标度量依据。 要获取有关目标的度量依据信息,请使用 metricsdst 子命令:
imqcmd metrics dst -t q -n XQueue -m ttl -u admin -p admin
此命令产生的输出结果类似如下内容(请参见表 9-10 中的数据说明):
-----------------------------------------------------------------------------
Msgs Msg Bytes Msg Count Total Msg Bytes (k) Largest
In Out In Out Current Peak Avg Current Peak Avg Msg (k)
-----------------------------------------------------------------------------
200 200 147200 147200 0 200 0 0 143 71 0
300 200 220800 147200 100 200 10 71 143 64 0
300 300 220800 220800 0 200 0 0 143 59 0
要获取有关目标的用户的信息,请使用下面的 metricsdst 子命令:
imqcmd metrics dst -t q -n SimpleQueue -m con -u admin -p admin
此命令产生的输出结果类似如下内容(请参见表 9-10 中的数据说明):
------------------------------------------------------------------
Active Consumers Backup Consumers Msg Count
Current Peak Avg Current Peak Avg Current Peak Avg
------------------------------------------------------------------
1 1 0 0 0 0 944 1000 525
imqcmd query
imqcmd query 命令的语法和选项如表 9-4 中所示,并带有该命令所提供的度量依据数据的说明。
表 9-4 imqcmd query 子命令语法
子命令语法
提供的度量依据数据
query bkr
[-b hostName:port]
[-int interval]
[-msp numSamples]有关当前存储在代理内存和持久性存储库中的消息个数和消息字节数目的信息(请参见“显示代理信息”)
或
metrics svc -n serviceName
[-b hostName:port]
[-int interval]
[-msp numSamples]有关指定的连接服务的当前已分配线程数和连接数的信息(请参见“显示连接服务信息”)
或
metrics dst -t destType
-n destName
[-b hostName:port]
[-int interval]
[-msp numSamples]有关指定目标的当前生成方的数目、活动和备份使用方的数目以及存储在内存和持久性存储库中的消息数和消息字节数的信息(请参见“显示目标信息”)
注意
由于 imqcmd query 提供的度量依据数据有限,“度量依据数据说明”一节的表中中未提供此工具。
Message Queue 代理日志文件
Message Queue 日志记录器获取代理代码、调试器和度量依据生成器等生成的信息,并将该信息写到多个输出通道:标准输出(控制台)、日志文件以及 Solaris 平台上的 syslog 守护程序进程。日志记录器在“日志记录器”中有所说明。
您可以指定日志记录器所收集的信息类型以及写到每个输出通道的类型。特别地,您可以指定希望将度量依据度量依据信息写入到日志文件。
过程:使用代理日志文件报告度量依据数据
本节讲述使用代理日志文件报告度量依据信息的过程。有关配置日志记录器的一般信息,请参见“日志记录”。
要使用日志文件来报告度量依据信息,请执行下列操作:
度量依据输出:日志文件
下面显示了到日志文件的代理度量依据输出样例(请参见表 9-7 和表 9-8 中的度量依据数据说明):
[21/Jul/2003:11:21:18 PDT]
Connections: 0 JVM Heap: 8323072 bytes (7226576 free) Threads: 0 (14-1010)
In: 0 msgs (0bytes) 0 pkts (0 bytes)
Out: 0 msgs (0bytes) 0 pkts (0 bytes)
Rate In: 0 msgs/sec (0 bytes/sec) 0 pkts/sec (0 bytes/sec)
Rate Out: 0 msgs/sec (0 bytes/sec) 0 pkts/sec (0 bytes/sec)
基于消息的监视 API
Message Queue 提供度量依据的监视功能,通过该功能,代理可以将度量依据数据写入到 JMS 消息,然后根据消息中包含的度量依据信息类型将它们发送到众多度量依据主题目标中的某一个目标。
您可以通过编写具有下列功能的客户机应用程序来访问此度量依据信息:订阅度量依据主题目标、使用这些目标中的消息以及处理消息中包含的度量依据信息。度量依据中介绍了通用方案。
共有五个度量依据主题目标,它们的名称以及传送到各个目标的度量依据消息的类型显示在表 9-5 中。
表 9-5 度量依据主题目标
主题名称
度量依据消息类型
mq.metrics.broker
代理度量依据
mq.metrics.jvm
Java 虚拟机度量依据
mq.metrics.destination_list
目标及其类型列表
mq.metrics.destination.queue.
monitoredDestinationName具有指定名称的队列的目标度量依据
mq.metrics.destination.topic.
monitoredDestinationName具有指定名称的主题的目标度量依据
过程:设置基于消息的监视
本节讲述使用基于消息的监视功能来收集度量依据信息的过程。该过程包括客户机开发和管理任务这两方面。
要设置基于消息的监视,请执行下列操作:
- 编写度量依据监视客户机。
有关以编程方式编写订阅度量依据主题目标、使用度量依据消息并从这些消息中提取度量依据数据的客户机的说明,请参见《Message Queue Java Client Developer's Guide》。
- 通过在 config.properties 文件中设置代理属性来配置代理的度量依据消息生成方:
- 设置需要对度量依据主题目标设置的任何访问控制。
请参见下面的“安全性和访问注意事项”中的讨论。
- 启动度量依据监视客户机。
当用户订阅度量依据主题时,系统就会自动创建度量依据主题目标。创建度量依据主题后,代理的度量依据消息生成方就会开始向度量依据主题发送度量依据消息。
安全性和访问注意事项
出于以下两个原因,需要限制对主题目标的访问:
出于这些方面的考虑,建议限制对度量依据主题目标的访问。
监视客户机的验证和授权控制与其他任何客户机都相同。只有保持在 Message Queue 用户信息库中的用户才允许连接代理。
您可以通过某个访问控制属性文件,限制对特定度量依据主题目标的访问,从而提供其他保护,如“授权用户: 访问控制属性文件”中所述。
例如,accesscontrol.properties 文件中的下列条目将拒绝除用户 1 和用户 2 之外的其他所有用户对 mq.metrics.broker 度量依据主题的访问。
下列条目将仅允许用户 user3 监视主题 t1。
topic.mq.metrics.destination.topic.t1.consume.deny.user=*
topic.mq.metrics.destination.topic.t1.consume.allow.user=user3
根据度量依据数据的敏感度不同,您也可以使用加密连接将度量依据监视客户机连接至代理。有关使用加密连接的信息,请参见“加密:使用基于 SSL 的服务(企业版)”。
度量依据输出:度量依据消息
使用基于消息的监视 API 获得的度量依据数据输出是您编写的度量依据监视客户机的一个函数。您只会受到代理中度量依据生成器提供的数据的限制。有关此数据的完整列表,请参见“度量依据数据说明”。
选择适当的监视工具
前面各节中讨论的每种监视工具都各有其优缺点。
例如,使用 imqcmd metrics 命令可以在您需要时迅速地抽取适合您需要的信息,但这会造成查看历史信息或者以编程方式操纵数据变得有些困难。
另一方面,日志文件可以提供度量依据数据的长期记录,但是日志文件中的信息很难解析为有意义的信息。
基于消息的监视 API 可用于轻松地提取您需要的信息、对其进行处理、以编程方式操纵或格式化数据以及提供图形或发送警报;但是您必须编写自定义应用程序以捕获并分析数据。
另外,这些工具中的每一种所收集到的由代理生成的度量依据信息的子集会稍有不同。有关哪些度量依据数据是由何种监视工具收集的信息,请参见“度量依据数据说明”。
表 9-6 从每种工具的正反两面对这些工具进行了比较。
表 9-6 度量依据监视工具的正面和反面因素
度量依据监视工具
正面因素
反面因素
imqcmd metrics
远程监视
便于抽样检查
在命令选项中设置报告的时间间隔,可以随时更改
易于选择感兴趣的特定数据
数据以简易的表格格式提供
单条命令无法获取所有数据
难于以编程方式分析数据
不能创建历史记录
难于看到历史趋势
日志文件
定期采样
创建历史记录
需要配置代理属性;必须关闭并重新启动代理才能生效
仅限本地监视
数据格式非常难于读取或解析;没有解析工具
报告时间间隔不能随时更改;所有度量依据数据也是如此
在数据的选择上不能提供灵活性
仅限代理度量依据;目标和连接服务度量依据不包括在内
如果时间间隔过短,性能可能会受影响
基于消息的监视 API
远程监视
易于选择感兴趣的特定数据
数据可以按照电子格式分析,并能够以任何格式提供
需要配置代理属性;必须关闭并重新启动代理才能生效
需要编写您自己的度量依据监视客户机
报告时间间隔不能随时更改;所有度量依据数据也是如此
度量依据数据说明
代理所报告的度量依据信息可以归为下列几类:
以下各节讲述每个类别中的可用度量依据数据。有关下列各表中提到的监视工具的信息,请参见“监视工具”。
JVM 度量依据
表 9-7 列出并说明了代理为代理进程 JVM 堆生成的度量依据数据,并显示了使用不同的度量依据监视工具可以获得哪些数据。
表 9-7 JVM 度量依据
度量依据数量
说明
imqcmd metrics bkr(metricType)
日志文件
度量依据消息(metrics topic)1
JVM 堆:可用内存
可用于 JVM 堆的内存量
是
(cxn)是
是(…jvm)
JVM 堆:总内存
当前的 JVM 堆大小
是
(cxn)是
是(…jvm)
JVM 堆:最大内存
JVM 堆可以达到的最大大小。
否
是2
是(…jvm)
2仅在代理启动时显示。
代理范围度量依据
表 9-8 列出并说明了代理所报告的有关代理范围内的度量依据信息的数据。它还显示了哪些数据可以使用不同的度量依据监视工具获得。
表 9-8 代理范围度量依据
度量依据数量
说明
imqcmd metrics bkr(metricType)
日志文件
度量依据消息(metrics topic)1
连接数据
Num connections
当前对代理打开的连接数
是
(cxn)是
是(…broker)
Num threads
当前使用的线程数
是
(cxn)是
否
Min threads
特定的线程数,达到该数量后,线程池中将维护此数量的线程供连接服务使用
是
(cxn)是
否
Max threads
特定的线程数,达到该数量后,线程池中将不会添加新的线程以供连接服务使用
是
(cxn)是
否
存储消息数据
Num messages
当前存储在代理内存和持久性存储库中的 JMS 消息数
否使用 query bkr
否
是(…broker)
Total message bytes
当前存储在代理内存和持久性存储库中的 JMS 消息字节数
否使用 query bkr
否
是(…broker)
消息流数据
Num messages in
自从代理上次启动以来流入该代理的 JMS 消息数
是
(ttl)是
是(…broker)
Message bytes in
自从代理上次启动以来流入该代理的 JMS 消息字节数
是
(ttl)是
是(…broker)
Num packets in
自从代理上次启动以来流入该代理的数据包(包括 JMS 消息和控制消息)数
是
(ttl)是
是(…broker)
Packet bytes in
自从代理上次启动以来流入该代理的数据包(包括 JMS 消息和控制消息)字节数
是
(ttl)是
是(…broker)
Num messages out
自从代理上次启动以来流出该代理的 JMS 消息数
是
(ttl)是
是(…broker)
Message bytes out
自从代理上次启动以来流出该代理的 JMS 消息字节数
是
(ttl)是
是(…broker)
Num packets out
自从代理上次启动以来流出该代理的数据包(包括 JMS 消息和控制消息)数
是
(ttl)是
是(…broker)
Packet bytes out
自从代理上次启动以来流出该代理的数据包(包括 JMS 消息和控制消息)字节数
是
(ttl)是
是(…broker)
Rate messages in
JMS 消息流入代理的当前速率
是
(rts)是
否
Rate message bytes in
JMS 消息字节流入代理的当前速率
是
(rts)是
否
Rate packets in
数据包(包括 JMS 消息和控制消息)流入代理的当前速率
是
(rts)是
否
Rate packet bytes in
数据包(包括 JMS 消息和控制消息)字节流入代理的当前速率
是
(rts)是
否
Rate messages out
JMS 消息流出代理的当前速率
是
(rts)是
否
Rate message bytes out
JMS 消息字节流出代理的当前速率
是
(rts)是
否
Rate packets out
数据包(包括 JMS 消息和控制消息)流出代理的当前速率
是
(rts)是
否
Rate packet bytes out
数据包(包括 JMS 消息和控制消息)字节流出代理的当前速率
是
(rts)是
否
目标数据
Num destinations
代理中的物理目标数
否
否
是(…broker)
连接服务度量依据
表 9-9 列出并说明了代理为各个连接服务所报告的度量依据数据。它还显示了哪些数据可以使用不同的度量依据监视工具获得。
表 9-9 连接服务度量依据
度量依据数量
说明
imqcmd metrics svc(metricType)
日志文件
度量依据消息(metrics topic)
连接数据
Num connections
当前打开的连接数
是
(cxn)
还有 query svc否
否
Num threads
所有连接服务当前总计使用的线程数
是
(cxn)
还有 query svc否
否
Min threads
特定的供所有连接服务使用的总计线程数,达到该数量后,线程池中将维护此数量的线程供连接服务使用
是
(cxn)否
否
Max threads
特定的供所有连接服务使用的总计线程数,达到该数量后,线程池中将不会添加新的线程以供连接服务使用
是
(cxn)否
否
消息流数据
Num messages in
自从代理上次启动以来流入连接服务的 JMS 消息数
是
(ttl)否
否
Message bytes in
自从代理上次启动以来流入连接服务的 JMS 消息字节数
是
(ttl)否
否
Num packets in
自从代理上次启动以来流入连接服务的数据包(包括 JMS 消息和控制消息)数
是
(ttl)否
否
Packet bytes in
自从代理上次启动以来流入连接服务的数据包(包括 JMS 消息和控制消息)字节数
是
(ttl)否
否
Num messages out
自从代理上次启动以来流出连接服务的 JMS 消息数
是
(ttl)否
否
Message bytes out
自从代理上次启动以来流出连接服务的 JMS 消息字节数
是
(ttl)否
否
Num packets out
自从代理上次启动以来流出连接服务的数据包(包括 JMS 消息和控制消息)数
是
(ttl)否
否
Packet bytes out
自从代理上次启动以来流出连接服务的数据包(包括 JMS 消息和控制消息)字节数
是
(ttl)否
否
Rate messages in
JMS 消息通过连接服务流入代理的当前速率。
是
(rts)否
否
Rate message bytes in
JMS 消息字节流入连接服务的当前速率
是
(rts)否
否
Rate packets in
数据包(包括 JMS 消息和控制消息)流入连接服务的当前速率
是
(rts)否
否
Rate packet bytes in
数据包(包括 JMS 消息和控制消息)字节流入连接服务的当前速率
是
(rts)否
否
Rate messages out
JMS 消息流出连接服务的当前速率
是
(rts)否
否
Rate message bytes out
JMS 消息字节流出连接服务的当前速率
是
(rts)否
否
Rate packets out
数据包(包括 JMS 消息和控制消息)流出连接服务的当前速率
是
(rts)否
否
Rate packet bytes out
数据包(包括 JMS 消息和控制消息)字节流出连接服务的当前速率
是
(rts)否
否
目标度量依据
表 9-9 列出并说明了代理为各个目标所报告的度量依据数据。它还显示了哪些数据可以使用不同的度量依据监视工具获得。
表 9-10 目标度量依据
度量依据数量
说明
imqcmd metrics dst(metricType)
日志文件
度量依据消息(metrics topic)1
使用方数据
Num active consumers
当前活动使用方数
是
(con)否
是
(…destName)Avg num active consumers
自从代理上次启动以来的平均活动使用方数
是
(con)否
是
(…destName)Peak num active consumers
自从代理上次启动以来的最大活动使用方数
是
(con)否
是
(…destName)Num backup consumers
当前备份使用方数(仅适用于队列)
是
(con)否
是
(…destName)Avg num backup consumers
自从代理上次启动以来的平均备份使用方数(仅适用于队列)
是
(con)否
是
(…destName)Peak num backup consumers
自从代理上次启动以来的最大备份使用方数(仅适用于队列)
是
(con)否
是
(…destName)存储消息数据
Num messages
当前存储在目标内存和持久性存储库中的 JMS 消息数
是
(con)
(ttl)
(rts)
还有 query dst否
是
(…destName)Avg num messages
自从代理上次启动以来存储在目标内存和持久性存储库中的平均 JMS 消息数
是
(con)
(ttl)
(rts)否
是
(…destName)Peak num messages
自从代理上次启动以来存储在目标内存和持久性存储库中的最大 JMS 消息数
是
(con)
(ttl)
(rts)否
是
(…destName)Total message bytes
当前存储在目标内存和持久性存储库中的 JMS 消息字节数
是
(ttl)
(rts)
还有 query dst否
是
(…destName)Avg total message bytes
自从代理上次启动以来存储在目标内存和持久性存储库中的平均 JMS 消息字节数
是
(ttl)
(rts)否
是
(…destName)Peak total message bytes
自从代理上次启动以来存储在目标内存和持久性存储库中的最大 JMS 消息字节数
是
(ttl)
(rts)否
是
(…destName)Peak message bytes
自从代理上次启动以来目标接收到的单个消息中 JMS 消息的最大字节数
是
(ttl)
(rts)否
是
(…destName)消息流数据
Num messages in
自从代理上次启动以来流入此目标的 JMS 消息数
是
(ttl)否
是
(…destName)Msg bytes in
自从代理上次启动以来流入此目标的 JMS 消息字节数
是
(ttl)否
是
(…destName)Num messages out
自从代理上次启动以来流出此目标的 JMS 消息数
是
(ttl)否
是
(…destName)Msg bytes out
自从代理上次启动以来流出此目标的 JMS 消息字节数
是
(ttl)否
是
(…destName)Rate num messages in
JMS 消息流入目标的当前速率
是
(rts)否
否
Rate num messages out
JMS 消息流出目标的当前速率
是
(rts)否
否
Rate msg bytes in
JMS 消息字节流入目标的当前速率
是
(rts)否
否
Rate Msg bytes out
JMS 消息字节流出目标的当前速率
是
(rts)否
否
磁盘使用情况数据
Disk reserved
基于目标文件的存储库中所有消息记录(活动的和空闲的)使用的磁盘空间(以字节为单位)
是
(dsk)否
是
(…destName)Disk used
基于目标文件的存储库中活动消息记录使用的磁盘空间(以字节为单位)
是
(dsk)否
是
(…destName)Disk utilization ratio
已用磁盘空间除以保留磁盘空间所得的商。比率越高,用于容纳活动消息时所占用的磁盘空间就越多
是
(dsk)否
是
(…destName)
性能问题疑难解答使用 Message Queue 服务支持应用程序时,可能会发生很多性能问题。这些问题包括:
下面会逐个讨论这些问题,并说明这些问题的可能起因及解决方案。
问题:客户机无法建立连接
症状:
可能原因:
要确认这是否就是问题的起因,请执行下列操作:
检查所有连接服务的状态:
如果某个连接服务的状态显示为 unknown 或 paused,则客户机将无法使用该服务建立连接。
要解决此问题,请执行下列操作:
要正确配置 SSL 服务,请参见“设置通过 TCP/IP 的基于 SSL 的服务”。
- 如果连接服务的状态显示为 paused,则可以恢复该服务(请参见“暂停和恢复连接服务”)。
要确认这是否就是问题的起因,请执行下列操作:
在代理日志中检查下面的条目:WARNING [B3004]: No threads are available to process a new connection on service ...Closing the new connection。
另请检查连接服务上的连接数以及当前使用的线程数:
每个连接都需要两个线程:一个用于外来消息,另一个用于外出消息(请参见“线程池管理器”)。
要解决此问题,请执行下列操作:
- 如果使用专用线程池模型 (imq.service_name. threadpool_model=dedicated),则最大连接数是该线程池中的最大线程数的一半。因此,要增加连接数,请增加线程池的大小 (imq.service_name.max_threads) 或切换到共享线程池模型。
- 如果使用共享线程池模型 (imq.service_name. threadpool_model=shared),则最大连接数是下面两个属性的乘积的一半。连接监视限制 (imq.service_name.connectionMonitor_limit) 和最大线程数 (imq.service_name.max_threads)。因此,要增加连接数,可以增加线程池的大小或增大连接监视限制。
- 最终,可支持的连接数(或连接上的吞吐量)将达到输出/输出限制。此时,可以使用多代理群集(请参见“使用群集(企业版)”)在群集内的代理实例之间分布连接。
- Solaris 或 Linux 平台上连接数所需的文件描述符不足(请参见“OS 定义的文件描述符限制”)。
TCP 待办事项设置可以存储在系统待办事项 (imq.portmapper.backlog) 中的同时连接请求数限制后,端口映射器才会拒绝额外的请求。(在 Windows 平台上,有一种硬编码的待办事项限制:Windows 台式机限制为 5,而 Windows 服务器限制为 200。)
出于待办事项限制而拒绝请求通常是一种由于同时连接请求数过多而导致的瞬态现象。
要确认这是否就是问题的起因,请执行下列操作:
检查代理日志,以查看是否在某些连接请求被接受的同时还有另外一些连接请求被拒绝。被拒绝的连接请求会返回 java.net.ConnectException: Connection refused 消息。
要解决此问题,请执行下列操作:
下列方法可用于解决 TCP 待办事项限制:
验证可能因为密码错误而失败,原因是在用户信息库中没有该用户的条目,或者该用户没有对连接服务的访问权限。
要确认这是否就是问题的起因,请执行下列操作:
检查代理日志中的条目,判断是否有 Forbidden 错误消息。此消息指明存在验证错误,但不会指明该错误的原因。
要解决此问题,请执行下列操作:
- 如果在用户信息库中没有该用户的条目,那么将该用户添加到用户信息库中(请参见“填充和管理用户信息库”)。
- 如果使用了错误的密码,请提供正确的密码。
- 如果访问控制属性设置不当,则编辑访问控制属性文件以授予连接服务权限(请参见“连接访问控制”)。
问题:连接的吞吐量太慢
症状:
可能原因:
- 与 TCP 相比,连接服务协议本身就慢。例如,基于 SSL 或基于 HTTP 的协议比 TCP 要慢(请参见图 9-5)。
要确认这是否就是问题的起因,请执行下列操作:
如果您使用的是基于 SSL 或基于 HTTP 的协议,请尝试使用 TCP,然后比较传送时间。
要解决此问题,请执行下列操作:
应用程序的要求通常会限定要使用的协议,因此您可以做的事情就很少了,无非是按“调整传输协议”中所述尝试调整协议而已。
要确认这是否就是问题的起因,请执行下列操作:
尝试调整协议,并查看是否发生了变化。
要解决此问题,请执行下列操作:
尝试按“调整传输协议”中所述调整协议。
要确认这是否就是问题的起因,请执行下列操作:
如果上述的每一条看来都不是造成连接吞吐量变慢的原因,请参见图 9-1以了解其他可能的瓶颈,并检查与下列问题相关的症状:
要解决此问题,请执行下列操作:
遵循前面有关问题疑难解答的各节中提供的问题解决方案指导。
问题:客户机无法创建消息生成方
症状:
可能原因:
限制某个目标所能支持的生成方 (maxNumProducers) 数目是避免消息在该目标上堆积的方法之一。
要确认这是否就是问题的起因,请执行下列操作:
检查目标(请参见“显示目标信息”):
输出结果将显示当前的生成方数目以及 maxNumProducers 的值。如果这两个值相同,则说明生成方的数量已达到所配置的限制。如果新的生成方被代理拒绝,代理将返回 ResourceAllocationException [C4088]: A JMS destination limit was reached 消息,且在代理日志中生成如下条目:[B4183]: Producer can not be added to destination。
要解决此问题,请执行下列操作:
增大 maxNumProducers 属性的值(请参见“更新目标属性”)。
要确认这是否就是问题的起因,请执行下列操作:
如果新的生成方被代理拒绝,代理将返回 JMSSecurityException [C4076]: Client does not have permission to create producer on destination 消息,并在代理日志中生成如下条目:[B2041]:Producer on destination denied 和 [B4051]: Forbidden guest。
要解决此问题,请执行下列操作:
更改访问控制属性,允许用户生成消息(请参见“目标访问控制”)。
问题:消息的生成过程发生延迟或变慢
症状:
可能原因:
当目标内存中的消息数或消息字节数达到配置的限制时,代理会尝试根据指定的限制行为节约内存资源。下列限制行为会使消息生成方变慢:
同样,如果代理范围的内存(对于所有目标)中消息数或消息字节数达到配置的限制,代理将尝试通过拒绝最新的消息来节约内存资源。
另外,如果达到了系统内存限制(由于目标或代理范围限制设置不正确),代理将采取越来越严格的操作来防止内存过载,包括限制消息生成方。
有关这些机制的讨论,请参见“管理内存资源和消息流”。
要确认这是否就是问题的起因,请执行下列操作:
如果某个消息因为达到了配置的消息限制而被代理拒绝,代理将返回JMSException [C4036]: A server error occurred,并在代理日志中生成下列条目:WARNING [B2011]: Storing of JMS message from IMQconn failed,后面跟有一条表明已达到限制的消息:
大多数情况下,您可以通过两种方式在发生拒绝之前检查消息限制情况:分别使用相应的 imqcmd 命令(请分别参见表 9-10和表 9-8)查询目标和代理并检查它们所配置的消息限制设置,以及监视当前在目标上(或者作为一个整体在代理中)的消息数或消息字节数。
要解决此问题,请执行下列操作:
有很多方法可以解决由于消息变得堆积而导致生成方变慢的问题。
如果代理无法访问数据存储或者将持久性消息写入数据存储,则生成方客户机将阻塞。如果达到了如前所述的目标或代理范围消息限制,也将发生此情况。
要确认这是否就是问题的起因,请执行下列操作:
如果代理无法写入数据存储库,它将在代理日志中生成下列条目之一:[B2011]: Storing of JMS message from connectionID failed 或 [B4004]:Failed to persist message messageID
要解决此问题,请执行下列操作:
- 如果是内置持久性,则尝试增大基于文件的数据存储的磁盘空间。
- 如果是 JDBC 兼容的数据存储,则检查插入的持久性是否正确配置(请参见附录 B“设置插入的持久性”)。如果是这样,请向数据库管理员咨询,以解决其他数据库问题。
如果连接太慢或消息服务器反应迟缓(由于 CPU 使用率太高或者内存资源不足导致),代理用于确认收到持久性消息的时间比连接工厂的 imqAckTimeout 属性的值允许的时间要长。
要确认这是否就是问题的起因,请执行下列操作:
如果超出了 imqAckTimeout 值,代理将返回 JMSException [C4000]: Packet acknowledge failed。
要解决此问题,请执行下列操作:
更改 imqAckTimeout 连接工厂属性的值(请参见“连接工厂受管理对象属性”)。
要确认这是否就是问题的起因,请执行下列操作:
要解决此问题,请执行下列操作:
调整 JVM(请参见“Java 虚拟机调整”)。
问题:消息在消息服务器中堆积
症状:
可能原因:
如果消息可以传送到的活动使用方太少,队列目标可能会随着消息的堆积而变得堆满了待办事项。只要有下列任何原因,都会发生此情况:
要确认这是否就是问题的起因,请执行下列操作:
要确定使用方不可用的原因,请检查目标上活动使用方的数量:
要解决此问题,请执行下列操作:
您可以根据使用方不可用的原因采取下列任意操作:
- 通过启动其他使用方客户机来为队列创建更多的活动使用方。
- 调整 imq.consumerFlowLimit 代理属性以优化对多个使用方的队列传送(请参见“多使用方队列性能”)。
- 指定队列的消息限制以及限制行为属性(请参见表 6-10)。例如,您可以指定 REMOVE_OLDEST 和 REMOVE_LOW_PRIORITY 限制行为,这些行为可以删除在内存中堆积的消息。
- 清除来自相应目标的所有消息(请参见“清除目标”)。
- 限制消息可以在内存中保留的时间:您可以重写生成方客户机以对每个消息都设置一个有效期值,也可以通过设置 imqOverrideJMSExpiration 和 imqJMSExpiration 连接工厂属性(请参见表 7-3)来覆盖共享一个连接的所有生成方的这些设置。
在这种情况下,主题的订阅者或队列的接收者使用消息的速度要比生成方发送消息的速度慢。会有一个或多个目标因为这种不平衡而堆满了消息。
要确认这是否就是问题的起因,请执行下列操作:
检查消息流入和流出代理的速率:
然后检查每个单独目标的流速:
要解决此问题,请执行下列操作:
- 优化使用方客户机代码。
- 对于队列目标,增大活动使用方的数目(请参见“多使用方队列性能”)。
影响对客户机确认过程的处理有两个因素:
要确认这是否就是问题的起因,请执行下列操作:
检查与数据包流相关的消息流。如果每秒数据包数与消息数的不成比例,则客户机确认可能有问题。
另外请检查客户机是否收到 JMSException [C4000]: Packet acknowledge failed 消息。
要解决此问题,请执行下列操作:
- 修改客户机使用的确认模式,例如切换到 DUPS_OK_ACKNOWLEDGEMENT 或 CLIENT_ACKNOWLEDGEMENT。
- 如果使用 CLIENT_ACKNOWLEDGEMENT 或事务会话,则将更多数量的消息组合到一个确认中。
- 调整使用方和连接流控制参数(请参见“客户机运行时消息流调整”)。
问题:消息服务器吞吐量呈间歇性
症状:
可能原因:
由于目标和代理的限制设置得不正确,代理采取了越来越严格的措施以防止内存过载,这样就导致代理变得非常迟缓,直到消息的堆积得到清除为止。
要确认这是否就是问题的起因,请执行下列操作:
在代理日志中检查内存小的情况 ([B1089]: In low memory condition, broker is attempting to free up resources),该情况后面会接有一个描述新内存状态和已用内存总量的条目。
另外请检查 JVM 堆中的可用内存:
当总 JVM 内存接近 JVM 内存最大值时,可用内存就会很小。
要解决此问题,请执行下列操作:
- 调整 JVM(请参见“Java 虚拟机调整”)。
- 增大系统交换空间。
问题:消息无法到达使用方
症状:
可能原因:
如果时钟之间不同步,则代理对消息有效期的计算可能会错误,从而导致消息超过它们的截止时间而被删除。
要确认这是否就是问题的起因,请执行下列操作:
检查所有计算机上的时钟。
要解决此问题,请执行下列操作:
同步时钟(请参见“系统时钟设置”)。
调整配置以提高性能系统调整
以下各节讲述您可以对操作系统、JVM 和通信协议所作的调整。
Solaris 调整:CPU 使用、分页/交换/磁盘 I/O
有关对操作系统的调整,请参见系统文档。
Java 虚拟机调整
默认情况下,代理使用大小为 192MB 的 JVM 堆。通常,这对于较大的消息负荷来说太小,应该增大。
当代理快要耗尽 Java 对象使用的 JVM 堆空间时,它将使用各种技术(如流控制和消息交换)来释放内存。在极端情况下,代理甚至关闭客户机连接以释放内存并减少消息内流。所以最好将最大 JVM 堆空间设置得足够大,以避免这种情况。
但是,与系统的物理内存相比,如果最大 Java 堆空间设置过大,代理将继续增大 Java 堆空间,直至整个系统耗尽内存。这会导致性能的降低、不可预计的代理崩溃和/或影响系统中运行的其他应用程序和服务的行为。通常,需要有足够的物理内存以便操作系统和其他应用程序在计算机上运行。
总的说来,好的方法是:估算正常和峰值系统内存容量,并配置 Java 堆大小,使其足以提供良好性能,但同时不应过大,以免引起系统内存问题。
要更改代理的最小和最大堆大小,请在启动代理时使用 -vmargs 命令行选项。例如:
此命令会将启动 Java 堆大小设置为 256MB,将最大 Java 堆大小设置为 1GB。
- 在 Solaris 上,如果通过 /etc/rc(即 /etc/init.d/imq)启动代理,请在 /etc/imq/imqbrokerd.conf 文件中指定代理的命令行参数。有关详细信息,请参见该文件中的注释。
- 在 Windows 上,如果将代理作为 Window 服务启动,请使用 imqsvcadmin install 命令的 -vmargs 选项指定 JVM 参数。请参见“服务管理器实用程序 (imqsvcadmin)”。
在任何情况下,请通过检查代理的日志文件或通过使用 imqcmd metrics bkr -m cxn 命令验证设置。
调整传输协议
选择了符合应用程序需要的协议后,基于该协议进行其他调整可以提高性能。
协议的性能可以使用下面三个代理属性进行修改:
对于 TCP 和 SSL 协议,这些属性会影响客户机和代理之间的消息传送速度。对于 HTTP 和 HTTPS 协议,这些属性会影响 Message Queue 隧道 servlet(在 Web 服务器上运行)和代理之间的消息传送速度。对于 HTTP/HTTPS 协议,还有其他可以影响性能的属性(请参见“HTTP/HTTPS 调整”)。
协议调整属性将在以下各节中讲述。
nodelay
nodelay 属性影响给定协议的 Nagle 算法(TCP/IP 上的 TCP_NODELAY 套接字级选项的值)。Nagle 算法用于提高使用慢速连接(例如广域网 (WAN))的系统上的 TCP 性能。
如果使用了此算法,TCP 将通过把多个数据捆绑为较大的数据包来尝试防止将多个小块数据发送到远程系统。如果写入套接字中的数据没有填满需要的缓冲区大小,协议将延迟发送数据包,直到缓冲区被填满,或者已经过了特定的延迟时间为止。填满了缓冲区或者发生了超时后,数据包将发送。
对于大多数消息传送应用程序,如果数据包发送过程中没有延迟(Nagle 算法未启用),则性能是最佳的。这是因为客户机和代理之间的大多数交互都是请求/响应交互:客户机向代理发送数据包,并等待响应。例如,典型的交互包括:
对于这些交互,大多数数据包都比缓冲区大小要小。这意味着如果使用 Nagle 算法,代理会在向使用方发送响应之前延迟几毫秒。
但是,在连接较慢以及不需要代理响应的情况下,Nagle 算法可以提高性能。例如,当客户机发送非持久性消息或者当客户机确认未被代理确认(DUPS_OK_ACKNOWLEDGE 会话)时,就属于这样的情况。
inbufsz/outbufsz
inbufsz 属性用于在读取来自套接字的数据的输入流上设置缓冲区大小。同样,outbufsz 用于设置代理用来将数据写入套接字的输出流的缓冲区大小。
通常,这两个参数都应该设置为比收发的平均数据包要稍大的值。一个很好的经验是将这些属性值设为平均数据包的大小再加上 1k(舍入为最接近的 k 值)。
例如,如果代理正在接收主体大小为 1k 的数据包,则该数据包的总体大小(消息主体 + 标题 + 属性)约为 1200 字节。大小为 2k(2048 字节)的 inbufsz 可以提供合理的性能。
增大 inbufsz 或 outbufsz(使其大于该值)可以稍微提高性能,但这样会增加每个连接所需的内存。
图 9-6 显示对大小为 1K 的数据包更改 inbufsz 的结果。
图 9-7 更改大小为 1K(1024 字节)的数据包的 inbufsz 的结果
图 9-8 显示对大小为 1K 的数据包更改 outbufsz 的结果。
图 9-8 更改大小为 1K(1024 字节)的数据包的 outbufsz 的结果
HTTP/HTTPS 调整
除了前面两节讨论的一般属性之外,HTTP/HTTPS 的性能还受到客户机向作为 Message Queue 隧道 servlet 宿主的 Web 服务器发出 HTTP 请求的速度的限制。
Web 服务器可能需要优化,以处理单个套接字上的多个请求。在 JDK 1.4 版及更高版本中,对 Web 服务器的 HTTP 连接会一直保持(对 Web 服务器的套接字保持打开),以使 Web 服务器在处理多个 HTTP 请求时使用的资源最小化。如果使用 JDK 1.4 版的客户机应用程序的性能比运行早期 JDK 版本的同一应用程序要低,则可能需要调整 Web 服务器的保持配置参数以提高性能。
除了这样的 Web 服务器调整之外,您还可以调整客户机轮询 Web 服务器的频率。HTTP 是一种基于请求的协议。这意味着使用基于 HTTP 的协议的客户机需要定期地检查 Web 服务器,以查看是否有消息在等待。imq.httpjms.http.pullPeriod 代理属性(以及相应的 imq.httpsjms.https.pullPeriod 属性)可指定 Message Queue 客户机运行时轮询 Web 服务器的频率。
如果 pullPeriod 值为 -1(默认值),客户机运行时将在前一个请求返回后立即轮询服务器,从而将各个客户机的性能最大化。结果,每个客户机连接都会在 Web 服务器中独占一个请求线程,这样可能会耗费 Web 服务器资源。
如果 pullPeriod 值为正数,客户机运行时将定期向 Web 服务器发送请求,以查看是否有挂起的数据。在这种情况下,客户机不会独占 Web 服务器中的请求线程。因此,如果有大量的客户机在使用 Web 服务器,您可以通过将 pullPeriod 设为正值来节约 Web 服务器资源。
调整基于文件的持久性存储库
有关调整基于文件的持久性存储库的信息,请参见“内置的持久性”。
代理调整
以下各节讲述为了提高性能而可以对代理属性作出的调整。
内存管理:增大代理在负荷下的稳定性
内存管理可以在逐个目标的级别上配置,也可以在系统范围级别(集中地对于所有目标)上配置。
使用目标限制
有关目标限制的信息,请参见“管理目标”。
使用系统范围限制
如果消息生成方的数目超过消息使用方的数目,则消息可能在代理中堆积。尽管代理确实包含限制生成方和在内存过小的情况下将消息交换出活动内存的机制(请参见“管理内存资源和消息流”),最好还是对代理可以保持的消息数和消息字节总数进行严格限制。
可以通过设置 imq.system.max_count 和 imq.system.max_size 代理属性来控制这些限制。有关设置代理属性的信息,请参见“编辑实例配置文件”或imqbrokerd 选项概述。
例如
imq.system.max_count=5000
上面定义的值表示代理最多仅能保留 5000 条未传送/未确认的消息。如果发送了其他消息,它们将被代理拒绝。如果消息是持久性的,当生成方尝试发送该消息时,会收到一个异常。如果消息是非持久性的,代理将自行废弃该消息。
若要让非持久性消息像持久性消息那样返回异常,请对客户机使用的连接工厂对象设置下列属性:
imqAckOnProduce = true
上面的设置会降低向代理发送非持久性消息的性能(客户机会等待回复后才发送下一条消息),但通常这是可以接受的,因为内流到代理的消息通常不是系统瓶颈。
如果在发送消息的过程中返回了异常,客户机应该暂停一会,然后再次重试发送。
多使用方队列性能
多队列使用方处理队列目标中消息的效率取决于可配置的队列目标属性,即活动使用方数目 (maxNumActiveConsumers) 和一次性可以传送到使用方的最大消息数 (consumerFlowLimit)。表 6-10 中介绍了这些属性。
要达到优化的消息吞吐量,必须有足够数量的活动使用方以适应队列的消息生成方的速率,并且队列中的消息必须以最大化使用速率的方式路由和传送给活动使用方。“多个使用方的队列传送”中介绍了在多个使用方之间平衡消息传送的一般机制。
如果消息在队列中堆积,这可能是因为没有足够的活动使用方来处理消息负荷。也可能是每批传送给使用方的消息太多,导致消息在使用方堆积。例如,如果每批的大小 (consumerFlowLimit) 太大,某个使用方就可能会收到一个队列中的所有消息,而其他活动使用方则一个也没收到。如果使用方速度特别快,这也不会成为问题。
但是如果使用方相对较慢,而您又希望将消息均匀地分布给它们,则需要将每批的大小减小。每批的大小越小,将消息传送到使用方所需的开销就越多。但是对于较慢的使用方,使用较小的批大小通常却能获得网络性能的提升。
客户机运行时消息流调整
本节讨论影响性能的流控制行为(请参见“客户机运行时配置”)。这些行为可配置为连接工厂被管理对象的属性。有关设置连接工厂属性的信息,请参见第 7 章“管理受管理对象”
消息流测量
客户机收发的消息(JMS 消息)以及 Message Queue 控制消息通过同一客户机 代理连接传递。如果控制消息(例如代理确认)的传送被 JMS 消息阻挡,则会发生延迟。为防止此类拥塞,Message Queue 会测量通过连接的 JMS 消息流。
JMS 消息是分批的(由 imqConnectionFlowCount 属性指定),因此只会传送集合编号;传送完一批后,JMS 消息的传送会挂起,而挂起的控制消息会传送。当另一批 JMS 消息传送后,接着又传送排队等候的控制消息,这样循环往复。
如果客户机正在执行需要代理作出大量响应的操作,imqConnectionFlowCount 的值应该保持较低;例如,当客户机正在使用 CLIENT_ACKNOWLEDGE 或 AUTO_ACKNOWLEDGE 模式、持久性消息、事务、队列浏览器时,或者当客户机正在添加或删除使用方时。从另一方面说,如果客户仅在使用 DUPS_OK_ACKNOWLEDGE 模式的连接上有简单的使用方,则可以增大 imqConnectionFlowCount 而不会降低性能。
消息流限制
在遇到本地资源(例如内存)限制之前,存在 Message Queue 客户机运行时可以处理的 JMS 消息数限制。如果达到了此限制,性能将受影响。因此,Message Queue 可以让您限制每个使用方(或每个连接)能够通过连接传送和能够在客户机运行时中缓冲以等待使用的消息数。
基于使用方的限制
当传送到客户机运行时的 JMS 消息数超过任意使用方的 imqConsumerFlowLimit 值时,将停止传送该使用方的消息。仅当该使用方的未使用消息数下降到低于 imqConsumerFlowThreshold 设置的值时才会恢复。
下例说明了如何使用这些限制:以主题使用方的默认设置为例
imqConsumerFlowLimit=1000
imqConsumerFlowThreshold=50
创建使用方后,代理将向此使用方传送第一批 1000 条消息(前提是有这么多),中间不会暂停。发送 1000 条消息后,代理将停止传送,除非客户机运行时要求更多消息。客户机运行将保留这些消息,直到应用程序处理它们为止。在要求代理发送下一批消息之前,客户机运行时会允许应用程序使用至少 50% (imqConsumerFlowThreshold) 的消息缓冲区容量(即 500 条消息)。
在同等情况下,如果阈值为 10%,则客户机运行时会等待应用程序使用至少 900 条消息,然后才会要求发送下一批消息。
下一批消息的大小按如下计算:
imqConsumerFlowLimit - (current number of pending msgs in buffer)
因此,如果 imqConsumerFlowThreshold 为 50%,则下一批的大小会在 500 和 1000 之间波动,这取决于应用程序处理消息的速度。
如果 imqConsumerFlowThreshold 设置得过高(接近 100%),代理就会发送较小的分批消息,这样会降低消息的吞吐量。如果该值过低(接近 0%),则客户机可以在代理传送下一组消息之前处理完剩余的缓冲消息,从而导致消息吞吐量的降低。通常,除非您有特别的性能或可靠性考虑,否则不需要更改 imqConsumerFlowThreshold 属性的默认值。
基于使用方的流控制(特别是 imqConsumerFlowLimit)是管理客户机运行时中内存的最好方法。通常,根据客户机应用程序的不同,您应该知道在任意连接上需要支持的使用方数、消息的大小以及可用于客户机运行时的内存总量。
基于连接的限制
但是在某些客户机应用程序中,使用方数量不是确定的,这取决于最终用户所作的选择。在这些情况下,您仍可以使用连接级流限制来管理内存。
连接级流控制可以限制针对一个连接上的所有使用方而缓冲的总消息数。如果此数字超过了 imqConnectionFlowLimit,则通过该连接进行的消息传送将停止,直到该总数降到连接限制以下为止(只有在将 imqConnectionFlowLimitEnabled 属性设置为 true 时,imqConnectionFlowLimit 才会启用)。
在会话中排队等候的消息数是使用该会话的消息使用方数量以及每个使用方的消息负荷的函数。如果客户机在生成或使用消息时表现出延迟,您通常可以通过下列操作提高性能:重新设计应用程序,以便在更大数量的会话之间分布消息生成方和使用方,或者在更大数量的连接之间分布会话。