症状:
发送持久性消息时,send 方法不返回,并且客户端发生阻塞。
发送持久性消息时,客户端收到异常。
生成方客户端速度变慢。
可能的原因:
可能的原因:代理上堆满了后备队列,使得消息生成方的执行速度变慢。
堆满后备队列的代理将消息堆积在代理内存中。当物理目的地内存中的消息数或消息字节数达到配置的限制时,代理会尝试根据指定的限制行为来节省内存资源。以下限制行为会使消息生成方速度减慢:
FLOW_CONTROL:代理不会立即确认收到持久性消息(这样就会阻塞生成方客户端)。
REJECT_NEWEST:代理将拒绝新的持久性消息。
同样,如果代理范围的内存(对于所有物理目的地)中消息数或消息字节数达到配置的限制,代理将尝试通过拒绝最新的消息来节省内存资源。另外,如果达到了系统内存限制(由于物理目的地或代理范围限制设置不正确),代理将采取愈加严格的操作来防止内存过载。这些操作包括限制消息生成方。
确认问题的起因:如果某个消息因为达到了配置的消息限制而被代理拒绝,代理将返回异常
JMSException [C4036]:发生服务器错误
且在代理日志中生成以下条目:
[B2011]:存储来自 IMQconn 的 JMS 消息失败。
随后又产生一条消息表明已达到内存限制:
[B4120]:无法在目的地 destName 上存储消息,因为会超出 maxNumMsgs 的容量。
如果超出的消息限制是在物理目的地上,或
[B4024]:已经超出目前系统中的最大消息数,正在拒绝消息。
如果消息限制是代理范围的。
通常,您可以在发生拒绝之前按如下方式检查消息限制情况:
查询物理目的地和代理,并检查其配置的消息限制设置。
使用相应的 imqcmd 命令,监视当前物理目的地或代理(作为一个整体)中的消息数或消息字节数。有关可以监视的度量以及用来获取它们的命令的信息,请参见第 18 章,度量参考。
解决此问题:
修改物理目的地上的(或代理范围的)消息限制,请小心不要超出内存资源。
通常,应该根据每个目的地来管理内存,这样才不会达到代理范围的消息限制。有关详细信息,请参见代理调整。
更改目的地上的限制行为,以便达到消息限制时不会减慢消息的生成,而是丢弃内存中的消息。
例如,您可以指定 REMOVE_OLDEST 和 REMOVE_LOW_PRIORITY 限制行为,这些行为可以删除在内存中堆积的消息(请参见表 15–1)。
可能的原因:代理无法将持久性消息保存到数据存储库中。
如果代理无法访问数据存储库或者无法将持久性消息写入数据存储库,则生成方客户端将受阻。如前所述,如果达到了目的地或代理范围的消息限制,也会发生这种情况。
确认问题的起因:如果代理无法写入数据存储库,它将在代理日志中生成以下条目之一:
[B2011]:存储来自 connectionID 的 JMS 消息失败或 [B4004]:无法持续消息 messageID。
解决此问题:
如果是基于文件的持久性,则尝试增大基于文件的数据存储库的磁盘空间。
如果是符合 JDBC 的数据存储库,则检查基于 JDBC 的持久性是否正确配置(请参见配置持久性数据存储库)。如果是这样,请向数据库管理员咨询,以解决其他数据库问题。
可能的原因:代理的确认超时时间太短。
由于连接太慢或代理反应迟缓(由于 CPU 占用率太高或者内存资源不足导致),代理用于确认收到持久性消息的时间比连接工厂的 imqAckTimeout 属性值所允许的时间要长。
确认问题的起因:如果超出了 imqAckTimeout 值,代理将返回异常
JMSException [C4000]:包确认失败
解决此问题:更改 imqAckTimeout 连接工厂属性的值(请参见可靠性和流控制)。
可能的原因:生成方客户端遇到了 JVM 限制。
确认问题的起因:
查明客户端应用程序是否收到了“内存不足”错误。
使用诸如 freeMemory、maxMemory 和 totalMemory 等运行时环境方法检查 JVM 堆中的可用内存。
解决此问题:调整 JVM(请参见Java 虚拟机调整)。