数据库关闭时保留 JMS 消息
JMS message preserve when DB down
应用程序概述:
在我的应用程序中,我们每天收到 60000 条消息。它使用 11 MDB 和 MessageListener 来订阅来自不同 OMB 队列的消息并进行处理。使用 weblogic 服务器和 JAP。每个 MDB 总共有 32 个实例,因为我们有 8 个不同的节点,每个节点的 max-beans-in-free-pool 是 4.
当前问题:
当数据库宕机时,在异常中捕获它并回滚事务上下文,以便将消息放回队列。我们检查 JMSXDeliveryCount 是否小于 100 它将重试,否则它将丢弃消息并发送带有消息引用的电子邮件。
问题:
消息丢失,100 次重试在几秒钟内到达。但 DB 可能会在 2 小时后启动。
建议的方法:
在处理消息之前检查数据库连接,如果数据库连接出现问题——在重新轮询后让线程休眠 5 分钟以检查连接。
在这种情况下,每个 MDB 可以在应用程序级别保留 32 条消息 (Tread),剩余的消息将在队列中。我们有 11 个 MDB,因此 (11*32) 个线程可能会在应用程序级别休眠。
我觉得在初始级别检查所有消息的数据库连接并在应用程序级别保持 352 条消息(控制 352 线程,可能是 weblogic 崩溃)直到数据库启动,这很糟糕。
在 MDB 级别或 weblogic 级别处理此问题的任何更好方法?
我不熟悉 Web Logic,但回答我对 IBM MQ 的了解。
您是否考虑过为您的应用程序接收消息的队列设置 Redelivery Limit
和 Error Destination
属性?如果一条消息的 JMSXDeliveryCount
属性 超过 Redelivery Limit
,那么该消息将被路由到 Error Destination
,基本上是一个队列或一个主题。您还可以为消息设置 Redelivery Delay Override
属性。
您可以编写单独的逻辑,将消息从 Error Destination
移动到您的应用程序从中接收消息的队列。这样消息就不会丢失。
更多详情here。
希望对您有所帮助。
容器管理事务 – 容器将处理它,而不是通过代码处理线程/消息重试。
容器将根据下面提到的 MDB 配置重试消息。
即在 weblogic-ejb-jar.xml 下:消息驱动描述符
<init-suspend-seconds>2</init-suspend-seconds>
从 2 秒重试开始。重试间隔秒数每次加倍,直到达到最大重试 300 秒。即 2、4、8 … 300
<max-suspend-seconds>300</max-suspend-seconds>
一旦达到 300 秒,容器将每 300 秒重试一次,直到解决故障原因。一旦问题得到解决,容器就会恢复 MDB 实例的正常处理。
<message-driven-descriptor>
<pool>
<max-beans-in-free-pool>4</max-beans-in-free-pool>
<initial-beans-in-free-pool>1</initial-beans-in-free-pool>
</pool>
<destination-jndi-name>XXX_FOREIGN_DEST_LOCAL@env_name@
</destination-jndi-name>
<connection-factory-jndi-name>XXX_FOREIGN_QCF_LOCAL@env_name@
</connection-factory-jndi-name>
<init-suspend-seconds>2</init-suspend-seconds>
<max-suspend-seconds>300</max-suspend-seconds>
</message-driven-descriptor>
应用程序概述:
在我的应用程序中,我们每天收到 60000 条消息。它使用 11 MDB 和 MessageListener 来订阅来自不同 OMB 队列的消息并进行处理。使用 weblogic 服务器和 JAP。每个 MDB 总共有 32 个实例,因为我们有 8 个不同的节点,每个节点的 max-beans-in-free-pool 是 4.
当前问题:
当数据库宕机时,在异常中捕获它并回滚事务上下文,以便将消息放回队列。我们检查 JMSXDeliveryCount 是否小于 100 它将重试,否则它将丢弃消息并发送带有消息引用的电子邮件。
问题: 消息丢失,100 次重试在几秒钟内到达。但 DB 可能会在 2 小时后启动。
建议的方法:
在处理消息之前检查数据库连接,如果数据库连接出现问题——在重新轮询后让线程休眠 5 分钟以检查连接。 在这种情况下,每个 MDB 可以在应用程序级别保留 32 条消息 (Tread),剩余的消息将在队列中。我们有 11 个 MDB,因此 (11*32) 个线程可能会在应用程序级别休眠。
我觉得在初始级别检查所有消息的数据库连接并在应用程序级别保持 352 条消息(控制 352 线程,可能是 weblogic 崩溃)直到数据库启动,这很糟糕。
在 MDB 级别或 weblogic 级别处理此问题的任何更好方法?
我不熟悉 Web Logic,但回答我对 IBM MQ 的了解。
您是否考虑过为您的应用程序接收消息的队列设置 Redelivery Limit
和 Error Destination
属性?如果一条消息的 JMSXDeliveryCount
属性 超过 Redelivery Limit
,那么该消息将被路由到 Error Destination
,基本上是一个队列或一个主题。您还可以为消息设置 Redelivery Delay Override
属性。
您可以编写单独的逻辑,将消息从 Error Destination
移动到您的应用程序从中接收消息的队列。这样消息就不会丢失。
更多详情here。
希望对您有所帮助。
容器管理事务 – 容器将处理它,而不是通过代码处理线程/消息重试。
容器将根据下面提到的 MDB 配置重试消息。
即在 weblogic-ejb-jar.xml 下:消息驱动描述符
<init-suspend-seconds>2</init-suspend-seconds>
从 2 秒重试开始。重试间隔秒数每次加倍,直到达到最大重试 300 秒。即 2、4、8 … 300
<max-suspend-seconds>300</max-suspend-seconds>
一旦达到 300 秒,容器将每 300 秒重试一次,直到解决故障原因。一旦问题得到解决,容器就会恢复 MDB 实例的正常处理。
<message-driven-descriptor>
<pool>
<max-beans-in-free-pool>4</max-beans-in-free-pool>
<initial-beans-in-free-pool>1</initial-beans-in-free-pool>
</pool>
<destination-jndi-name>XXX_FOREIGN_DEST_LOCAL@env_name@
</destination-jndi-name>
<connection-factory-jndi-name>XXX_FOREIGN_QCF_LOCAL@env_name@
</connection-factory-jndi-name>
<init-suspend-seconds>2</init-suspend-seconds>
<max-suspend-seconds>300</max-suspend-seconds>
</message-driven-descriptor>