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

如何实现ActiveMQ Classic向ActiveMQ Artemis转发消息?

问题

尝试让ActiveMQ Classic代理将消息转发至部署了相同队列的ActiveMQ Artemis代理,Classic侧配置如下:

<networkConnectors>
     <networkConnector uri="static:(tcp://172.18.0.3:61616)" name="artemis" userName="artemis" password="artemis"/>
</networkConnectors>

Classic启动无报错,但Artemis日志出现以下错误:

2025-04-14 11:37:39,763 WARN [org.apache.activemq.artemis.core.server] AMQ222216: Security problem while authenticating: AMQ229031: Unable to validate user from 172.18.0.2:57000. Username: null; SSL certificate subject DN: unavailable
2025-04-14 11:37:39,763 WARN [org.apache.activemq.artemis.core.protocol.openwire.OpenWireConnection] Errors occurred during the buffering operation
javax.jms.IllegalStateException: Cannot add a producer to a connection that had not been registered: localhost->ce2321bbff98-40547-1744630417600-30:2
at org.apache.activemq.artemis.core.protocol.openwire.OpenWireConnection$CommandProcessor.processAddProducer(OpenWireConnection.java:1230) ~[artemis-openwire-protocol-2.39.0.jar:2.39.0]
at org.apache.activemq.command.ProducerInfo.visit(ProducerInfo.java:108) ~[activemq-client-5.18.6.jar:5.18.6]
at org.apache.activemq.artemis.core.protocol.openwire.OpenWireConnection.act(OpenWireConnection.java:356) [artemis-openwire-protocol-2.39.0.jar:2.39.0]
at org.apache.activemq.artemis.core.protocol.openwire.OpenWireConnection.bufferReceived(OpenWireConnection.java:299) [artemis-openwire-protocol-2.39.0.jar:2.39.0]
at org.apache.activemq.artemis.core.remoting.server.impl.RemotingServiceImpl$DelegatingBufferHandler.bufferReceived(RemotingServiceImpl.java:723) [artemis-server-2.39.0.jar:2.39.0]
at org.apache.activemq.artemis.core.remoting.impl.netty.ActiveMQChannelHandler.channelRead(ActiveMQChannelHandler.java:73) [artemis-core-client-2.39.0.jar:2.39.0]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) [netty-codec-4.1.115.Final.jar:4.1.115.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:333) [netty-codec-4.1.115.Final.jar:4.1.115.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:455) [netty-codec-4.1.115.Final.jar:4.1.115.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) [netty-codec-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) [netty-transport-4.1.115.Final.jar:4.1.115.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) [netty-common-4.1.115.Final.jar:4.1.115.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.115.Final.jar:4.1.115.Final]
at org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run(ActiveMQThreadFactory.java:118) [artemis-commons-2.39.0.jar:2.39.0]

解决方案

修复当前networkConnector问题

日志核心问题为认证时用户名为null,进而导致未注册连接就添加生产者,可通过以下步骤修复:

  1. 修正Classic的networkConnector配置:
    将认证信息直接嵌入URI,确保连接Artemis时正确传递用户名密码:
    <networkConnectors>
         <networkConnector uri="static:(tcp://artemis:artemis@172.18.0.3:61616)" name="artemis"/>
    </networkConnectors>
    
    或补充bridgeUserName和bridgePassword参数,明确转发消息时的认证信息:
    <networkConnectors>
         <networkConnector uri="static:(tcp://172.18.0.3:61616)" name="artemis" 
                           userName="artemis" password="artemis"
                           bridgeUserName="artemis" bridgePassword="artemis"/>
    </networkConnectors>
    
  2. 检查Artemis的OpenWire acceptor配置:
    确保Artemis的broker.xml中开启OpenWire协议 acceptor:
    <acceptors>
        <acceptor name="openwire-acceptor">tcp://0.0.0.0:61616?protocols=OPENWIRE</acceptor>
    </acceptors>
    
    同时确认artemis用户具备连接、发送消息的权限:
    • 在artemis-users.properties中确保用户存在:artemis=artemis
    • 在artemis-roles.properties中配置角色权限:artemis=amq

替代方案(若上述方法无效)

如果networkConnector方式无法满足需求,可尝试以下方案:

  • 使用ActiveMQ Classic消息桥(Bridge):
    相比networkConnector,Bridge更适合点对点精准转发,示例配置:
    <bridges>
        <bridge name="classic-to-artemis-bridge">
            <queueName>YOUR_QUEUE_NAME</queueName>
            <bridgeUri>tcp://172.18.0.3:61616</bridgeUri>
            <userName>artemis</userName>
            <password>artemis</password>
            <clientId>bridge-client</clientId>
            <dispatchAsync>true</dispatchAsync>
        </bridge>
    </bridges>
    
  • 使用Apache Camel路由消息:
    通过Camel编写路由规则,支持复杂消息转换和逻辑,核心示例:
    from("activemq:queue:YOUR_QUEUE_NAME")
        .to("activemq:queue:YOUR_QUEUE_NAME?brokerURL=tcp://172.18.0.3:61616&username=artemis&password=artemis");
    
  • 自定义JMS转发程序:
    编写Java客户端程序,从Classic消费消息后发送到Artemis,完全控制转发逻辑和认证流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:12:02