Spring DefaultJmsListenerContainerFactory在JBoss EAP 7上丢弃消息。

问题描述 投票:0回答:1

我的Spring JMS出厂配置如下。

@Bean(name = "jmsListenerFactory")
public DefaultJmsListenerContainerFactory jmsListenerFactory() throws Exception {
    DefaultJmsListenerContainerFactory container = new DefaultJmsListenerContainerFactory();
    container.setErrorHandler(new MqErrorHandler());
    container.setConnectionFactory(connectionFactory);
    container.setTransactionManager(transactionManager);
    container.setConcurrency("5-10");
    return container;
}   

监听器设置:

@JmsListener(destination = ACK_QUEUE, containerFactory = "jmsListenerFactory")
@Transactional
public void receive(String response) throws Exception {
    try {
        logger.debug(response);
        Msg ackNack = (Msg) unmarshaller.unmarshal(new StringReader(response));
        ... and so on
        ... should acknowledge JMS and commit DB update
}

JTA事务管理器

public JtaTransactionManager jbossTransactionManager() throws Exception {
    JtaTransactionManager transactionManager = new JtaTransactionManager();
    transactionManager.setTransactionManagerName("java:/TransactionManager");
    return transactionManager;
}

我有一个Oracle数据库和一个通过JNDI包含的JMS连接工厂资源,都是XA兼容的。

问题是,一些JMS消息没有进入监听器。它们100%提供给了队列,但好像它们只是 "消失 "了。即使是TRACE级别的日志中也没有记录或错误报告。

没有任何其他的东西在监听这个队列,类似的事务也在同一个队列中得到成功处理。我不能以任何有保证的方式重现它,而且它完全是间歇性的。

有什么想法吗?

spring ibm-mq jboss7.x spring-jms jta
1个回答
1
投票

这里要吸取的教训是永远不要假设以下几点。

"没有其他东西在监听这个队列..."

有一些方法可以尝试并验证这一点。

  1. 检查当前有多少进程的INPUT队列是开放的

    DIS QL(QUEUENAME) IPPROCS

  2. 显示当前队列打开的所有连接,使用 OPENOPTS 其中包括 MQOO_INPUT*,这将同时显示IP地址(如果是客户端连接)和客户端提交的应用程序名称(APPLTAG)。

    DIS CONN(*) TYPE(ALL) WHERE(OBJNAME EQ QUEUENAME)

  3. 以上两个都只显示了一个时间点的视图,如果你想找到一个正在连接从队列中读取消息然后断开连接的应用,那么你可能看不到它。 就像@MoragHughson在评论中提到的那样,启动一个活动跟踪,寻找到这个队列的连接,看看连接的IPsapplication名称是否符合预期,这样做的好处是,你可以在一段时间内看到所有连接到队列的东西。 下面是一个使用IBM MQ v9.1或更高版本的amqsevt并以IBM MQ v9.0或更高版本的队列管理器为目标的一个方法的例子(这依赖于一个叫做 jq). 下面的例子将运行到5分钟(300秒)没有任何活动,或者直到有一个键被按下为止(您可以通过增加该键来增加时间)。-w 值)。)

#Replace the string _REPLACE_WITH_QMGR_NAME_ with your queue manager name in both places.
#Replace the string _REPLACE_WITH_QUEUE_NAME_ with your queue name.

amqsevt -m _REPLACE_WITH_QMGR_NAME_ -t '$SYS/MQ/INFO/QMGR/_REPLACE_WITH_QMGR_NAME_/ActivityTrace/ConnectionId/#' -w 300 -o json | jq -r '
.eventData
| [.channelName, .channelType, .connectionName, .applName, .remoteProduct, .remoteVersion] as $x
| ( .activityTrace[]
    | select(.objectName == "_REPLACE_WITH_QUEUE_NAME_") | [.operationTime]
      + $x
      + [.operationId, .objectName, .resolvedQueueName, .reasonCode.value, .putDate, .putTime] )
| @csv
'

0
投票

问题已经解决,因为DEV队列管理器正在默默地消耗消息.这是无效的配置。

© www.soinside.com 2019 - 2024. All rights reserved.