Sun Java System Message Queue 3.7 UR1 管理指南

调整配置以提高性能

以下各节讲述配置调整如何影响性能。

系统调整

以下各节讲述您可以对操作系统、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。

在任何情况下,都应当通过检查代理的日志文件或通过使用 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 算法用于提高使用慢速连接(例如广域网 (Wide-area Network, WAN))的系统上的 TCP 性能。

如果使用了此算法,TCP 将通过把多个数据捆绑为较大的包来尝试防止将多个小块数据发送到远程系统。如果写入套接字中的数据没有填满需要的缓冲区大小,协议将延迟发送包,直到缓冲区被填满,或者经过了特定的延迟时间为止。填满了缓冲区或者发生了超时后,包将被发送。

对于大多数消息传送应用程序,如果包发送过程中没有延迟(Nagle 算法未启用),则性能是最佳的。这是因为客户端与代理之间的大多数交互都是请求/响应交互:客户端向代理发送数据包,并等待响应。例如,典型的交互包括:

对于这些交互,大多数包都比缓冲区大小要小。这意味着如果使用 Nagle 算法,代理会在向使用方发送响应之前延迟几毫秒。

但是,在连接较慢以及不需要代理响应的情况下,Nagle 算法可以提高性能。例如,客户端发送非持久性消息或者客户端确认未被代理确认(DUPS_OK_ACKNOWLEDGE 会话)就属于这样的情况。

inbufsz/outbufsz

inbufsz 属性用于在读取来自套接字的数据的输入流上设置缓冲区大小。同样,outbufsz 用于设置代理用来将数据写入套接字的输出流的缓冲区大小。

通常,这两个参数都应该设置为比收发的平均包稍大的值。一个很好的经验是将这些属性值设为平均包的大小再加上 1k(舍入为最接近的 k 值)。例如,如果代理正在接收主体大小为 1k 的包,则该包的总体大小(消息主体+标题+属性)约为 1200 字节;大小为 2k(2048 字节)的 inbufsz 可以提供合理的性能。增大 inbufszoutbufsz(使其大于该值)可以稍微提高性能,但这样会增加每个连接所需的内存。

HTTP/HTTPS 调整

除了前面两节讨论的一般属性之外,HTTP/HTTPS 的性能还受到客户端向作为 Message Queue 隧道 Servlet 宿主的 Web 服务器发出 HTTP 请求的速度的限制。

Web 服务器可能需要优化,以处理单个套接字上的多个请求。在 JDK 1.4 版及更高版本中,与 Web 服务器的 HTTP 连接会一直保持活动状态(与 Web 服务器的套接字保持打开状态),以尽量减少 Web 服务器在处理多个 HTTP 请求时使用的资源。如果使用 JDK 1.4 版的客户端应用程序的性能比运行早期 JDK 版本的同一应用程序要低,则可能需要调整 Web 服务器的 keep-alive 配置参数以提高性能。

除了这样的 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_countimq.system.max_size 代理属性来控制这些限制。

例如:

imq.system.max_count=5000

上面定义的值表示代理最多只能保存 5000 条未传送/未确认的消息。如果发送了其他消息,它们将被代理拒绝。如果消息是持久性的,当生成方尝试发送该消息时,会收到一个异常。如果消息是非持久性的,代理将在不给出任何提示的情况下丢弃该消息。

如果在发送消息的过程中返回了异常,客户端应该暂停片刻,然后再次尝试发送。(请注意,异常绝不会是由于代理未能接收消息而引发的;所引发的异常都是由发送方客户端检测到的。)

多使用方队列性能

多队列使用方处理队列目的地中的消息的效率取决于下列可配置的队列目的地属性:

要达到最优的消息吞吐量,必须有足够数量的活动使用方以适应队列的消息生成速率,并且队列中的消息必须以最大化使用速率的方式路由和传送给活动使用方。Sun Java SystemTM Message Queue Technical Overview中介绍了在多个使用方之间平衡消息传送的一般机制。

如果消息在队列中堆积,这可能是因为没有足够的活动使用方来处理消息负载。也可能是每批传送给使用方的消息太多,导致消息在使用方堆积。例如,如果每批的大小 (consumerFlowLimit) 太大,某个使用方就可能会收到一个队列中的所有消息,而其他活动使用方则一个也没有收到。如果使用方速度特别快,这也不会成为问题。

但是如果使用方相对较慢,而您又希望将消息均匀地分配给它们,则需要将每一批的大小减小。每一批的大小越小,将消息传送到使用方所需的开销就越多。但是,对于较慢的使用方,使用较小的批大小通常能获得网络性能的提升。

客户端运行时环境消息流调整

在本节中将会讨论影响性能的流控制行为(请参见客户端运行时环境配置)。这些行为可配置为连接工厂受管理对象的属性。有关设置连接工厂属性的信息,请参见第 8 章,管理受管理对象

消息流度量

客户端收发的消息(有效负荷消息)以及 Message Queue 控制消息通过同一客户端-代理连接传递。如果控制消息(例如代理确认)被有效负荷消息的传送阻挡,则控制消息的传送会发生延迟。为防止此类拥塞,Message Queue 会度量通过连接进行的有效负荷消息流。

有效负荷消息是成批的(由连接工厂属性 imqConnectionFlowCount 指定),以便只传送数目设定的一组消息。传送完一批后,将暂停有效负荷消息的传送,而只传送暂挂的控制消息。当另一批有效负荷消息传送后,接着又传送暂挂的控制消息,如此循环往复。

如果客户端执行的是需要代理作出大量响应的操作,则 imqConnectionFlowCount 应保持较低的值:例如,当客户端使用的是 CLIENT_ACKNOWLEDGE AUTO_ACKNOWLEDGE 模式、持久性消息、事务或队列浏览器,或者正在添加或删除使用方时。从另一方面来说,如果客户端仅在使用 DUPS_OK_ACKNOWLEDGE 模式的连接上有简单的使用方,则可以增大 imqConnectionFlowCount 而不会降低性能。

消息流限制

在遇到本地资源(例如内存)限制之前,存在 Message Queue 客户端运行时环境可以处理的有效负荷消息数限制。如果达到了此限制,性能将受影响。因此,Message Queue 允许您限制每个使用方(或每个连接)能够通过连接传送和能够在客户端运行时环境中缓冲以等待使用的消息数。

使用方流限制

当传送到客户端运行时环境的有效负荷消息数超过任意使用方的 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 属性才会启用。)

在会话中排队的消息数是使用该会话的消息使用方数量以及每个使用方的消息负载的函数。如果客户端在生成或使用消息时表现出延迟,您通常可以通过下列操作来提高性能:重新设计应用程序,以便在更大数量的会话之间分布消息生成方和使用方,或者在更大数量的连接之间分布会话。