基于Apache Camel+ActiveMQ Artemis集群+JTA的会话连接固定问题
解决方案:固定JMS会话至同一Artemis节点
针对你遇到的JTA事务关闭会话后Camel监听器切换节点导致的性能问题,以下是几个可直接落地的解决思路:
1. 配置Artemis连接工厂使用固定节点负载均衡策略
修改ActiveMQ Artemis连接工厂配置,强制使用固定负载均衡策略,让每个连接绑定到初始建立连接的节点,避免自动切换:
Java配置类示例
@Bean public ActiveMQConnectionFactory artemisConnectionFactory() { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://dc1-node1:61616,tcp://dc1-node2:61616,tcp://dc2-node1:61616"); // 指定固定负载均衡策略类 factory.setConnectionLoadBalancingPolicyClassName("org.apache.activemq.artemis.api.core.client.loadbalance.FixedConnectionLoadBalancingPolicy"); // 关闭初始连接失败时的跨节点切换(按需调整) factory.setFailoverOnInitialConnection(false); return factory; }
application.yml配置示例
spring: artemis: broker-url: tcp://dc1-node1:61616,tcp://dc1-node2:61616,tcp://dc2-node1:61616 properties: connectionLoadBalancingPolicyClassName: org.apache.activemq.artemis.api.core.client.loadbalance.FixedConnectionLoadBalancingPolicy failoverOnInitialConnection: false
该策略会让连接始终使用首次建立连接的节点,故障转移时也仅切换到同配置内的备选节点,不会跨DC随意跳转。
2. 调整Camel JMS组件的会话复用配置
Camel默认在事务结束后销毁会话,通过配置会话池和缓存级别,实现会话复用,避免频繁创建新连接导致的节点切换:
@Bean public JmsComponent jmsComponent(ConnectionFactory connectionFactory, UserTransactionManager transactionManager) { JmsComponent component = new JmsComponent(); component.setConnectionFactory(connectionFactory); // 启用连接池 component.setUsePooledConnection(true); // 配置池化参数(按需调整) component.setMaxConnections(20); component.setMaxSessionsPerConnection(10); // 绑定JTA事务管理器 component.setTransactionManager(transactionManager); component.setTransacted(true); // 缓存消费者与会话,事务结束后保持会话打开 component.setCacheLevelName("CACHE_CONSUMER"); return component; }
CACHE_CONSUMER级别会让Camel持久化缓存消费者和会话资源,避免每次事务完成后销毁重建,从而稳定保持与同一节点的连接。
3. 配置Narayana JTA的节点亲和性
启用Narayana messagehub后,通过配置事务资源的节点亲和性,确保JMS连接与事务绑定到同一节点:
narayana.properties配置
# 指定仅在指定节点恢复事务资源 com.arjuna.ats.jta.recovery.message.xaRecoveryNodes=dc1-node1,dc1-node2 # 固定事务资源的节点归属 com.arjuna.ats.jms.connection.nodeAffinity=fixed
Spring Boot配置
narayana: messagehub: enabled: true connection-factory: artemisConnectionFactory # 指定优先绑定的节点前缀,限制连接范围 node-prefix: dc1-
4. 结合Artemis集群节点分组
在Artemis集群中配置节点分组,让Camel服务仅连接到指定DC的节点组,避免跨DC切换:
修改Artemis broker.xml配置节点组
<cluster-connections> <cluster-connection name="dc1-cluster"> <connector-ref>netty-connector</connector-ref> <message-load-balancing>ON_DEMAND</message-load-balancing> <discovery-group-ref discovery-group-name="dc1-discovery"/> <group-name>dc1-group</group-name> </cluster-connection> </cluster-connections>
连接工厂指定节点组
factory.setClusterGroupNames(Collections.singletonList("dc1-group"));
连接只会在同组节点间故障转移,结合固定负载均衡策略,可稳定绑定到同一节点。
内容的提问来源于stack exchange,提问作者Ian Cox
相关产品推荐
相关产品推荐

