![]() | |
Sun Java System Message Queue 3 2005Q1 管理指南 |
第 11 章
分析和调整消息服务本章包括大量有关如何分析和调整 Message Queue 服务以优化消息传送应用程序性能的主题。包括下列主题:
关于性能本节提供有关性能调整的一些背景信息。
性能调整过程
您的消息传送应用程序的性能取决于该应用程序与 Message Queue 服务之间的交互。因此,若要获得最佳性能,则需要应用程序开发者和管理员的共同努力。
优化性能的过程从应用程序设计开始,一直持续到部署应用程序之后对消息服务的调整阶段。性能调整过程包括下列阶段:
上述过程常常需要反复进行。在应用程序的部署过程中,Message Queue 管理员应该评估消息服务器是否适用于应用程序的总体性能要求。如果基准检验测试符合这些要求,管理员就可以按本章中所述调整系统。但是,如果基准检验测试不符合性能要求,则可能需要重新设计应用程序或者修改部署体系结构。
性能方面
通常,性能是对消息服务将消息从生产方传送到使用方时的速度和效率的一种衡量。但是,取决于您的需要,可能会有几个不同的性能方面对您特别重要。
连接负荷 系统所能支持的消息生产方、消息使用方或并行连接的数量。
消息吞吐量 每秒钟能通过消息传送系统抽取的消息数或消息字节数。
稳定性 消息服务的总体可用性,或者当负荷较重或发生故障时性能的下降程度。
效率 消息的传送效率,这是一种与使用的计算资源相关的消息吞吐量的衡量。
这些不同的性能方面总而言之是相辅相成的。如果消息吞吐量很高,则意味着消息在消息服务器上作为待办事项累积的可能性就会变小,因此延迟时间也应该较低(单条消息可以很快地传送)。但是,延迟可能取决于许多因素:通信链接的速度、消息服务器的处理速度和客户机的处理速度,以及其他众多方面。
在任何情况下,性能都有几个不同方面。哪些方面对您最重要?这通常要取决于特定应用程序的要求。
基准检验
基准检验是为消息传送应用程序创建测试套件,并针对此测试套件衡量消息吞吐量或其他性能方面的一种过程。
例如,您可以创建这样一个测试套件:一定数量的生产方客户机使用一定数量的连接、会话和消息生成器,将标准大小的持久性或非持久性消息按照某个特定速率发送至队列或主题(这完全取决于消息传送应用程序的设计)。同样,测试套件中还包括一定数量的使用方客户机,它们使用一定数量的连接、会话和特定类型的消息使用器(通过特定的确认模式来使用测试套件的物理目标中的消息)。
使用标准的测试套件可以衡量消息的生成和使用之间所花的时间或者消息的平均吞吐速率,您还可以监视系统以观察连接线程使用情况、消息存储数据、消息流数据以及其他相关度量。这样就可以提高消息的生成速率、消息生产方的数量或者其他变量,直到性能受到负面影响为止。可能达到的最大吞吐量就是消息服务配置的基准。
使用此基准可以修改测试套件的某些特征。控制所有可能影响性能的因素时请小心(请参见影响性能的应用程序设计因素),您可以记录这些因素导致基准发生了哪些变化。例如,您可以将连接数或消息大小增加五倍或十倍,并记下对性能产生的影响。
相反,您也可以将基于应用程序的因素保持不变,而以某种控制方式更改代理配置(例如,更改连接属性、线程池属性、JVM 内存限制、限制行为、内置与插入的持久性等),并记下这些更改如何影响性能。
当您需要通过调整消息服务来增加所部署的应用程序的性能时,这种应用程序基准检验可以提供非常有价值的信息。基准检验可用于更准确地预测所作的更改或一系列更改产生的影响。
通常,基准检验应该在受控制的测试环境下运行,并且运行足够长的时间,以使消息服务能够稳定。(性能在启动时会受到实时编译的负面影响,因为要将 Java 代码转换为机器代码。)
基线使用模式
部署并运行消息传送应用程序后,建立基线使用模式是很重要的。您需要知道何时发生峰值需求,并且需要能够量化该需求。例如,需求通常会随最终用户的数量、活动级别、一天当中的时间,或者以上所有这些因素而发生波动。
要建立基线使用模式,您需要在一段较长的时间内监视消息服务器,来查看如下数据:
还可以使用度量数据中提供的平均值和峰值。
将这些基线度量数据与设计时的期望值进行比较是非常重要的。通过执行此操作,可以检查客户机代码是否运转正常:例如,检查连接是否未保持打开或者已使用的消息是否仍然保留在未确认状态。这些编码错误会消耗消息服务器资源,并可能极大地影响性能。
基线使用模式有助于确定如何调整系统以优化性能。例如:
通常,您对使用模式了解得越多,就能越好地将系统调整为这些模式。并计划将来的需要。
影响性能的因素消息延迟和消息吞吐量是两个主要的性能指示器,它们通常取决于典型消息在完成消息传送过程中的各个步骤时所需的时间。下面步骤显示了如何以持久、可靠的方式传送消息。这些步骤将在插图之后讲述。
图 11-1 通过 Message Queue 服务传送消息
由于这些步骤是连续的,所以任何步骤都可能成为消息从生产方客户机到使用方客户机的传送过程的瓶颈。这些步骤中的大多数都取决于消息传送系统的物理特征:网络带宽、计算机处理速度和消息服务器体系结构等等。但是,有一些步骤还取决于消息传送应用程序的特征和该应用程序要求的可靠性级别。
以下各小节讨论应用程序设计因素和消息传送系统因素这二者对性能的影响。尽管应用程序设计和消息传送系统因素在消息的传送过程中交互紧密,但它们彼此是独立的。
影响性能的应用程序设计因素
应用程序的设计决策对消息传送的总体性能有很大影响。
对性能影响最大的主要是那些影响消息传送的可靠性因素。包括下列因素:
其他影响性能的应用程序设计因素有:
接下来的几节讲述这些因素当中的每一个对消息传送性能所产生的影响。通常,性能和可靠性应该折衷。增加可靠性的因素可能会导致性能降低。
表 11-1 显示各个应用程序设计因素大体上如何影响消息传送性能。该表显示了两个方案(一个高可靠性、低性能方案和一个高性能、低可靠性方案)和分别相应于这两个方案的应用程序设计因素选项。在这两种极端情况之间,有很多可以同时影响可靠性和性能的选项和折衷。
注
在接下来的图中,性能数据是在一个使用基于文件的持久性双 CPU、1002 Mhz Solaris 8 系统上生成的。性能测试首先预热 Message Queue 代理,使实时编译器优化系统,并启动持久性数据库。
代理预热后,会创建单个生产方和单个使用方,并在 30 秒钟内生成消息。系统将记录使用方接收所有生成的消息所需的时间,并计算吞吐率(每秒收到的消息数)。对于表 11-1 中所示的不同应用程序设计因素组合,此情形会重复出现。
传送模式(持久性/非持久性消息)
持久性消息能够在消息服务器发生故障的情况下保证消息的传送。代理会把消息存储在持久性存储中,直到所有预期的使用方都确认已使用消息为止。
通过代理处理持久性消息比处理非持久性消息要慢,理由如下:
持久性和非持久性模式的性能之间可以有很大的差别。图 11-2 比较了在两种可靠的传送情况下持久性和非持久性消息的吞吐量:同时将 10k 大小的消息传送至队列和长期订阅的主题。两种情况下都使用 AUTO_ACKNOWLEDGE 确认模式。
图 11-2 传送模式的性能影响
使用事务
事务是一种保证,保证在事务会话中生成和使用的所有消息将作为一个单元进行处理或不进行处理(回滚)。
Message Queue 支持本地事务和分布式事务。
消息在事务会话中生成或确认时比在非事务会话中要慢,理由如下:
确认模式
确保可靠传送 JMS 消息的一种机制是,客户机确认使用了由 Message Queue 消息服务器传送给它的消息。
如果在客户机尚未确认消息之前就关闭了会话,或者如果消息服务器在处理确认之前发生了故障,代理将重新传送该消息,并设置一个 JMSRedelivered 标志。
对于非事务会话,客户机可以选择三种确认模式之一,这三种模式有其各自的性能特征:
(CLIENT_ACKNOWLEDGE 模式的用法与事务的用法类似,不同之处在于:它不能保证当提供商在处理过程中发生故障时,所有确认都将一起处理)。
确认模式影响性能的原因如下:
长期与非长期订阅
主题目标的订户可以归为两类,即长期订阅和非长期订阅的订户。
长期订阅的可靠性较高,但吞吐较慢,原因如下:
图 11-3 比较了两种情况下的长期订阅和非长期订阅主题目标的吞吐量:10K 大小的持久性和非持久性消息。两种情况下都使用 AUTO_ACKNOWLEDGE 确认模式。
从图 11-3 中可以看到只有在持久性消息情况下,使用长期订阅的性能影响才会很明显,出现这种影响是因为持久性消息只有在长期订阅时才会永久存储,如上文所述。
图 11-3 订阅类型的性能影响
使用选择器(消息过滤)
应用程序的开发者常常需要将消息组的目标定为特定使用方。实现此愿望的方法有两种:将每组消息分别指向唯一的物理目标;或者是仅使用单个物理目标,并为每个使用方注册一个或多个选择器。
选择器是一种只请求特定消息的字符串,这些消息的属性值应该与传送到特定使用方的字符串匹配。例如,选择器 NumberOfOrders >1 仅传送 NumberOfOrders 属性值为 2 或更大值的消息。
将使用方注册到选择器会降低性能(与使用多个物理目标相比),因为会需要进行额外的处理,以处理每个消息。如果使用选择器,则必须对它进行解析,以使它与将来的消息匹配。另外,路由每个消息时,都必须检索该消息的属性,并与选择器相比较。但是,使用选择器为消息传送应用程序提供了更大的灵活性。
消息大小
消息大小会影响性能是因为从生产方客户机到代理以及从代理到使用方客户机之间必须传递更多的数据,并且对于持久性消息,必须存储更大的消息。
但是,通过将较小的消息成批地变为一个消息,对各个消息的路由和处理就可以变得尽可能地简单,从而获得总体性能的提高。此时,就会丢失有关各个消息的状态的信息。
图 11-4 比较了在两种情况下,1k、10k 和 100k 大小的消息的吞吐量(KB/秒):持久性和非持久性消息。每种情况都将消息发送至队列目标,并使用 AUTO_ACKNOWLEDGE 确认模式。
图 11-4 显示在这两种情况下,传送较大消息的开销都比传送较小消息时要少。您还可以看到在 1k 和 10k 大小的消息上出现的情况:非持久性消息较持久性消息接近 50% 的性能提高在 100k 大小的消息上并未得到体现,可能是因为在这种情况下,网络带宽已经成为消息吞吐量的瓶颈。
图 11-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 支持连接服务中所述的连接服务(及相应协议)。
协议的选择基于应用程序的要求(加密、通过防火墙访问等),但是所作的选择会影响总体性能。
图 11-5 传输协议速度
图 11-5 反映不同协议技术的性能特征:
消息服务器体系结构
Message Queue 消息服务器可以作为单个代理实现,也可以作为多个互相连接的代理实例(即代理群集)实现。
随着连接到代理的客户机数量以及所传送的消息数量的不断增加,代理最终将超出资源限制(例如文件描述符、线程和内存限制)。适应不断增加的负荷的方法之一是将更多的代理实例添加到 Message Queue 消息服务器,从而将客户机连接以及消息路由和传送分布到多个代理。
通常,如果客户机(特别是消息生产方客户机)均匀地分布在群集中,则这种调整最为有效。由于在群集的代理之间传送消息会涉及到开销,因此连接数有限或消息传送速率有限的群集,其性能可能会比单个代理要低。
您也可以使用代理群集来优化网络带宽。例如,您可能希望在群集内的一组远程代理之间使用低速的长途网络链路,而在客户机与其各自的代理实例之间使用高速链接进行连接。
有关群集的详细信息,请参见第 9 章“使用代理群集”。
代理限制和行为
消息服务器可能需要处理的消息吞吐量是消息服务器所支持的消息传送应用程序的使用模式的一项功能。但是,消息服务器在资源方面有限:内存、CPU 周期等。因此,在消息服务器变得无响应或不稳定的位置,它可能会崩溃。
Message Queue 消息服务器具有管理内存资源并防止代理用尽内存的内置机制。这些机制包括可配置的消息数限制,或代理可以拥有的消息字节数或其各自的物理目标,以及当达到物理目标限制时可以实施的一组行为。
通过仔细地监视和调整,这些可配置机制可以用于平衡消息的内流和外流,以使系统过载不会发生。尽管这些机制会造成开销并限制消息的吞吐量,但它们可以维护操作的完成性。
数据存储库性能
Message Queue 既支持内置的持久性,也支持插入的持久性。内置的持久性是基于文件的数据存储库。插入的持久性使用 Java 数据库连接 (JDBC) 接口,并需要 JDBC 兼容的数据存储库。
内置的持久性明显比插入的持久性要快,但是 JDBC 兼容的数据库系统可以提供应用程序需要的冗余、安全性和管理功能。
如果是内置持久性,您可以通过指定让持久性操作将内存中状态与数据存储库同步,从而将可靠性增至最大。这有助于消除因系统崩溃而导致的数据丢失,但代价是性能的下降。
客户机运行时配置
Message Queue 客户机运行时可提供客户机应用程序及其与 Message Queue 消息服务的接口。它支持客户机向物理目标发送消息以及接收来自这些目标的消息所需的所有操作。客户机运行时是可配置的(通过设置连接工厂属性值),使您可以设置通常能够提高性能和消息吞吐量的属性和行为。
例如,Message Queue 客户机运行时支持下列可配置行为:
- 连接流测量 (imqConnectionFlowCount),此行为有助于防止由于 JMS 消息和 Message Queue 控制消息通过同一连接时所形成的流引起的拥塞。
- 连接流限制 (imqConnectionFlowLimit),此行为有助于通过限制等待使用的、可以通过连接传送到客户机运行时的消息数,来避免客户机的资源限制。
- 使用方流限制 (imqConsumerFlowLimit),此行为有助于改进在多用户队列传送情况下用户之间的负荷平衡(因此向任何一个用户发送的消息数都是均衡的),并有助于阻止连接上的任何一个用户影响连接上的其他用户。此属性可以限制每个使用方等待使用的、可以通过连接传送到客户机运行时的消息数。还可以将该属性配置为队列目标属性 (consumerFlowLimit)。
有关这些行为和用来配置这些行为的属性的详细信息,请参见客户机运行时消息流调整。
调整配置以提高性能系统调整
以下各节讲述您可以对操作系统、JVM 和通信协议所作的调整。
Solaris 调整:CPU 使用、分页/交换/磁盘 I/O
有关对操作系统的调整,请参见系统文档。
Java 虚拟机调整
默认情况下,代理使用大小为 192MB 的 JVM 堆。通常,这对于较大的消息负荷来说太小,应该增大。
当代理快要耗尽 Java 对象使用的 JVM 堆空间时,它将使用各种技术(如流控制和消息交换)来释放内存。在极端情况下,代理甚至关闭客户机连接以释放内存并减少消息内流。所以最好将最大 JVM 堆空间设置得足够大,以避免这种情况。
但是,与系统的物理内存相比,如果最大 Java 堆空间设置过大,代理将继续增大 Java 堆空间,直至整个系统耗尽内存。这会导致性能的降低、不可预计的代理崩溃和/或影响系统中运行的其他应用程序和服务的行为。通常,需要有足够的物理内存以便操作系统和其他应用程序在计算机上运行。
总的说来,好的方法是:估算正常和峰值系统内存容量,并配置 Java 堆大小,使其足以提供良好性能,但同时不应过大,以免引起系统内存问题。
要更改代理的最小和最大堆大小,请在启动代理时使用 -vmargs 命令行选项。例如:
/usr/bin/imqbrokerd -vmargs "-Xms256m -Xmx1024m"
此命令会将启动 Java 堆大小设置为 256MB,将最大 Java 堆大小设置为 1GB。
- 在 Solaris 或 Linux 上,如果通过 /etc/rc*(即 /etc/init.d/imq)启动代理,请在 /etc/imq/imqbrokerd.conf (Solaris) 或 /etc/opt/sun/mq/imqbrokerd.conf (Linux) 文件中指定代理的命令行参数。有关详细信息,请参见该文件中的注释。
- 在 Windows 上,如果将代理作为 Window 服务启动,请使用 imqsvcadmin install 命令的 -vmargs 选项指定 JVM 参数。请参见第 13 章“命令参考”中的 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(使其大于该值)可以稍微提高性能,但这样会增加每个连接所需的内存。
图 11-7 显示对大小为 1K 的包更改 inbufsz 的结果。
图 11-7 更改大小为 1K(1024 字节)的包的 inbufsz 的结果
图 11-8 显示对大小为 1K 的包更改 outbufsz 的结果。
图 11-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 服务器资源。
调整基于文件的持久性存储
有关调整基于文件的持久性存储的信息,请参见持久性管理器。
代理调整
以下各节讲述为了提高性能而可以对代理属性作出的调整。
内存管理:增大代理在负荷下的稳定性
内存管理可以在逐个目标的级别上配置,也可以在系统范围级别(集中地对于所有目标)上配置。
使用物理目标限制
有关物理目标限制的信息,请参见第 6 章“管理物理目标”。
使用系统范围限制
如果消息生产方的数目超过消息使用方的数目,则消息可能在代理中堆积。代理包含限制生产方和在内存过小的情况下将消息交换出活动内存的机制,但最好还是对代理可以保持的消息数和消息字节总数进行严格限制。
可以通过设置 imq.system.max_count 和 imq.system.max_size 代理属性来控制这些限制。
例如
imq.system.max_count=5000
上面定义的值表示代理最多仅能保留 5000 条未传送/未确认的消息。如果发送了其他消息,它们将被代理拒绝。如果消息是持久性的,当生产方尝试发送该消息时,会收到一个异常。如果消息是非持久性的,代理将自行废弃该消息。
若要让非持久性消息像持久性消息那样返回异常,请对客户机使用的连接工厂对象设置下列属性:
imqAckOnProduce = true
上面的设置会降低向代理发送非持久性消息的性能(客户机会等待回复后才发送下一条消息),但通常这是可以接受的,因为内流到代理的消息通常不是系统瓶颈。
如果在发送消息的过程中返回了异常,客户机应该暂停一会,然后再次重试发送。
多使用方队列性能
多队列使用方处理队列目标中消息的效率取决于下列可配置的队列目标属性:
要达到优化的消息吞吐量,必须有足够数量的活动使用方以适应队列的消息生产方的速率,并且队列中的消息必须以最大化使用速率的方式路由和传送给活动使用方。Sun Java System Message Queue 技术概述中介绍了在多个使用方之间平衡消息传送的一般机制。
如果消息在队列中堆积,这可能是因为没有足够的活动使用方来处理消息负荷。也可能是每批传送给使用方的消息太多,导致消息在使用方堆积。例如,如果每批的大小 (consumerFlowLimit) 太大,某个使用方就可能会收到一个队列中的所有消息,而其他活动使用方则一个也没收到。如果使用方速度特别快,这也不会成为问题。
但是如果使用方相对较慢,而您又希望将消息均匀地分布给它们,则需要将每批的大小减小。每批的大小越小,将消息传送到使用方所需的开销就越多。但是对于较慢的使用方,使用较小的批大小通常却能获得网络性能的提升。
客户机运行时消息流调整
本节讨论影响性能的流控制行为(请参见客户机运行时配置)。这些行为可配置为连接工厂受管理对象的属性。有关设置连接工厂属性的信息,请参见第 8 章“管理受管理对象”。
消息流测量
客户机收发的消息(JMS 消息)以及 Message Queue 控制消息通过同一客户机 代理连接进行传递如果控制消息(例如代理确认)的传送被 JMS 消息阻挡,则会发生延迟。为防止此类拥塞,Message Queue 会测量通过连接的 JMS 消息流。
JMS 消息是成批的(由 imqConnectionFlowCount 属性指定),因此只会传送一组 JMS 消息。传送完一批后,将暂停 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——(缓冲区中当前暂挂的消息数)
因此,如果 imqConsumerFlowThreshold 为 50%,则下一批的大小会在 500 和 1000 之间波动,这取决于应用程序处理消息的速度。
如果 imqConsumerFlowThreshold 设置得过高(接近 100%),代理就会发送较小的分批消息,这样会降低消息的吞吐量。如果该值过低(接近 0%),则客户机可以在代理传送下一组消息之前处理完剩余的缓冲消息,从而导致消息吞吐量的降低。通常,除非您有特别的性能或可靠性考虑,否则不需要更改 imqConsumerFlowThreshold 属性的默认值。
基于使用方的流控制(特别是 imqConsumerFlowLimit)是管理客户机运行时中内存的最好方法。通常,根据客户机应用程序的不同,您应该知道在任意连接上需要支持的使用方数、消息的大小以及可用于客户机运行时的内存总量。
基于连接的限制
但是在某些客户机应用程序中,使用方数量不是确定的,这取决于最终用户所作的选择。在这些情况下,您仍可以使用连接级流限制来管理内存。
连接级流控制可以限制针对一个连接上的所有使用方而缓冲的总消息数。如果此数目超过了 imqConnectionFlowLimit,则通过该连接进行的消息传送将停止,直到该总数降到连接限制以下为止。(只有在将 imqConnectionFlowLimitEnabled 属性设置为 true 时,imqConnectionFlowLimit 才会启用)。
在会话中暂挂的消息数是使用该会话的消息使用方数量以及每个使用方的消息负荷的函数。如果客户机在生成或使用消息时表现出延迟,您通常可以通过下列操作提高性能:重新设计应用程序,以便在更大数量的会话之间分布消息生产方和使用方,或者在更大数量的连接之间分布会话。