You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Camel/ActiveMQ开启transacted=true后每秒生成DEBUG事务日志问题

问题:Apache Camel事务配置下空队列每秒生成DEBUG日志的原因

我是Apache Camel初学者,正在学习Manning出版的《Camel in Action》一书。按照第9章的说明配置了事务管理器,配置如下:

<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="tcp://${activemq.host}:${activemq.port}" />
</bean>

<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
      init-method="start" destroy-method="stop">
    <property name="maxConnections" value="2" />
    <property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>

<bean id="jmsTxnManager" class="org.springframework.jms.connection.JmsTransactionManager">
    <property name="connectionFactory" ref="pooledConnectionFactory" />
</bean>

<bean id="activemq" class="org.apache.camel.component.activemq.ActiveMQComponent">
    <property name="connectionFactory" ref="pooledConnectionFactory" />
    <property name="transacted" value="true" />
    <property name="transactionManager" ref="jmsTxnManager"/>
</bean>

我还配置了一个简单的消费者路由:

<route id="exAroute">
    <from uri="activemq:{{mq.in}}"/>
    <transacted/>
    <log message="${body}"/>
</route>

当我运行Camel时,即使队列是空的,每秒都会生成一组DEBUG日志:

10:54:30.873 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.springframework.jms.connection.JmsTransactionManager - Creating new transaction with name [JmsConsumer[TEST_IN]]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
10:54:30.873 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.springframework.jms.connection.JmsTransactionManager - Created JMS transaction on Session [PooledSession { ActiveMQSession {id=ID:computer-60122-1666796067926-1:2:1,started=true} java.lang.Object@192cac46 }] from Connection [PooledConnection { ConnectionPool[ActiveMQConnection {id=ID:computer-60122-1666796067926-1:2,clientId=ID:computer-60122-1666796067926-0:1,started=true}] }]
10:54:31.885 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.activemq.ActiveMQMessageConsumer - remove: ID:computer-60122-1666796067926-1:2:1:2, lastDeliveredSequenceId: -1
10:54:31.885 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.springframework.jms.connection.JmsTransactionManager - Initiating transaction commit
10:54:31.885 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.springframework.jms.connection.JmsTransactionManager - Committing JMS transaction on Session [PooledSession { ActiveMQSession {id=ID:computer-60122-1666796067926-1:2:1,started=true} java.lang.Object@192cac46 }]
10:54:31.885 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.activemq.ActiveMQSession - ID:computer-60122-1666796067926-1:2:1 Transaction Commit :null
10:54:31.885 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.activemq.ActiveMQSession - ID:computer-60122-1666796067926-1:2:1 Transaction Rollback, txid:null

我想知道出现这种情况的原因是什么?我的配置是否存在错误?我已经花了2小时研究这个问题但没有进展,希望能得到帮助,提前感谢。

附:如果我向队列中放入消息,路由可以正常执行:

10:59:21.829 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.activemq.TransactionContext - Begin:TX:ID:computer-60151-1666796352835-1:2:1
10:59:21.829 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.camel.component.jms.DefaultJmsMessageListenerContainer - Received message of type [class org.apache.activemq.command.ActiveMQTextMessage] from consumer [PooledMessageConsumer { ActiveMQMessageConsumer { value=ID:computer-60151-1666796352835-1:2:1:5, started=true } }] of transactional session [PooledSession { ActiveMQSession {id=ID:computer-60151-1666796352835-1:2:1,started=true} java.lang.Object@296def58 }]
10:59:21.829 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.camel.component.jms.EndpointMessageListener - activemq://TEST_IN consumer received JMS message: ActiveMQTextMessage {commandId = 5, responseRequired = true, messageId = ID:computer-60156-1666796361583-1:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:computer-60156-1666796361583-1:1:1:1, destination = queue://TEST_IN, transactionId = null, expiration = 0, timestamp = 1666796361809, arrival = 0, brokerInTime = 1666796361809, brokerOutTime = 1666796361819, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@4db30c0e, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = test}
10:59:21.859 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.camel.spring.spi.TransactionErrorHandler - Transaction begin (0x76adb233) redelivered(false) for (MessageId: ID:computer-60156-1666796361583-1:1:1:1:1 on ExchangeId: ID-computer-1666796353110-0-1))
10:59:21.859 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.springframework.jms.connection.JmsTransactionManager - Participating in existing transaction
10:59:21.859 [Camel thread #2 - JmsConsumer[TEST_IN]] INFO exAroute - test
10:59:21.859 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.camel.spring.spi.TransactionErrorHandler - Transaction commit (0x76adb233) redelivered(false) for (MessageId: ID:computer-60156-1666796361583-1:1:1:1:1 on ExchangeId: ID-computer-1666796353110-0-1))
10:59:21.859 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.springframework.jms.connection.JmsTransactionManager - Initiating transaction commit
10:59:21.859 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.springframework.jms.connection.JmsTransactionManager - Committing JMS transaction on Session [PooledSession { ActiveMQSession {id=ID:computer-60151-1666796352835-1:2:1,started=true} java.lang.Object@296def58 }]
10:59:21.859 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.activemq.ActiveMQSession - ID:computer-60151-1666796352835-1:2:1 Transaction Commit :TX:ID:computer-60151-1666796352835-1:2:1
10:59:21.859 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.activemq.TransactionContext - Commit: TX:ID:computer-60151-1666796352835-1:2:1 syncCount: 2
10:59:21.869 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.activemq.ActiveMQMessageConsumer - remove: ID:computer-60151-1666796352835-1:2:1:5, lastDeliveredSequenceId: 844
10:59:21.869 [Camel thread #2 - JmsConsumer[TEST_IN]] DEBUG org.apache.activemq.ActiveMQSession - ID:computer-60151-1666796352835-1:2:1 Transaction Rollback, txid:null

问题原因与解决方案

1. 根本原因:事务型消费者的短轮询机制

你配置的是事务型JMS消费者,当ActiveMQComponent设置transacted=true并关联JmsTransactionManager时,Camel底层使用的DefaultJmsMessageListenerContainer会默认采用短轮询策略:

  • 每1秒启动一次事务,尝试从队列拉取消息
  • 若队列无消息,事务会被提交,随后立即开启下一轮询
  • 日志中的Transaction Commit :null和Transaction Rollback, txid:null是空轮询后的正常事务收尾操作,并非错误,但会产生冗余DEBUG日志

2. 配置优化方案

(1)延长轮询间隔

在ActiveMQComponent中添加receiveTimeout参数,调整空队列时的轮询间隔,减少日志生成频率:

<bean id="activemq" class="org.apache.camel.component.activemq.ActiveMQComponent">
    <property name="connectionFactory" ref="pooledConnectionFactory" />
    <property name="transacted" value="true" />
    <property name="transactionManager" ref="jmsTxnManager"/>
    <property name="receiveTimeout" value="5000"/> <!-- 设置为5秒轮询一次 -->
</bean>

(2)启用长轮询

ActiveMQ支持长轮询,消费者会保持连接直到有消息或超时,避免频繁创建事务。只需在连接工厂的URL中添加useAsyncSend=true:

<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="tcp://${activemq.host}:${activemq.port}?useAsyncSend=true" />
</bean>

(3)降低日志级别

如果只是不想看到DEBUG级别的事务日志,可在日志配置中将org.springframework.jms.connection.JmsTransactionManager和org.apache.activemq.ActiveMQSession的级别调整为INFO或WARN,过滤冗余输出。

3. 配置正确性说明

你的核心事务配置是正确的:

  • 连接池、事务管理器与ActiveMQ组件的关联逻辑无误
  • 消息能正常消费并提交事务,证明事务流程工作正常
    空队列的日志只是轮询机制的副产品,不属于配置错误

内容的提问来源于stack exchange,提问作者burkheart14

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:50:30