如何将 JMS 消息从 WildFly 10 发送到远程 ActiveMQ
Posted
技术标签:
【中文标题】如何将 JMS 消息从 WildFly 10 发送到远程 ActiveMQ【英文标题】:How to send JMS messages from WildFly 10 to remote ActiveMQ 【发布时间】:2017-01-10 01:47:34 【问题描述】:在互联网上摸索了这么多之后,令人惊讶的是,我找不到使用带有 ActiveMQ (Artemis) 的 WildFly 10 中的 JMS 推送到远程消息队列的示例配置。更糟糕的是standalone-full.xml
没有绑定到模式(为什么???),当我最终找到它的 XSD here on GitHub 时,它没有包含说明每个节点/属性的含义以及可以放入哪些值的文档什么。
下面是standalone-full.xml的原始配置。
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
<server name="default">
<security-setting name="#">
<role name="guest" delete-non-durable-queue="true" create-non-durable-queue="true" consume="true" send="true"/>
</security-setting>
<address-setting name="#" message-counter-history-day-limit="10" page-size-bytes="2097152" max-size-bytes="10485760" expiry-address="jms.queue.ExpiryQueue" dead-letter-address="jms.queue.DLQ"/>
<http-connector name="http-connector" endpoint="http-acceptor" socket-binding="http"/>
<http-connector name="http-connector-throughput" endpoint="http-acceptor-throughput" socket-binding="http">
<param name="batch-delay" value="50"/>
</http-connector>
<in-vm-connector name="in-vm" server-id="0"/>
<http-acceptor name="http-acceptor" http-listener="default"/>
<http-acceptor name="http-acceptor-throughput" http-listener="default">
<param name="batch-delay" value="50"/>
<param name="direct-deliver" value="false"/>
</http-acceptor>
<in-vm-acceptor name="in-vm" server-id="0"/>
<jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
<jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
<connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>
<connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>
<pooled-connection-factory name="activemq-ra" transaction="xa" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm"/>
</server>
</subsystem>
下面是我的 CDI 队列客户端,它能够将消息发布到 WildFly 中的本地 Artemis 实例。
@ApplicationScoped
public class QueueClient
private static final Gson GSON = new Gson();
@Resource(mappedName = "java:jboss/DefaultJMSConnectionFactory")
private ConnectionFactory connectionFactory;
public void sendMessage(String destinationName, Object message) throws JMSException
try (Connection conn = connectionFactory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE))
Queue queue = session.createQueue(destinationName);
final Message consignment = session.createMessage();
consignment.setStringProperty("MEDIA_TYPE", "application/json");
consignment.setStringProperty("BODY", GSON.toJson(message));
session.createProducer(queue).send(consignment);
我的目标:将消息发布到远程 ActiveMQ 实例。
我有什么:server url
、topic name
、username
和 password
。
我的问题:如何修改配置来实现这个目标?
另类问题:如果以上都不能回答,我还有什么方法可以实现这个目标?
谢谢!
【问题讨论】:
【参考方案1】:您是否检查过以下文档。
https://docs.jboss.org/author/display/WFLY10/Connect+a+pooled-connection-factory+to+a+Remote+Artemis+Server
它可能解决了您当前的问题。
谢谢。
编辑:对这篇文章的负面标记。
正如上面列出的文档清楚地描述的那样。 您需要创建一个使用远程连接器的池连接工厂,并且远程连接器引用远程 Active MQ 服务器的 IP x 套接字。 请参阅有关如何执行此操作的文档,前三个步骤。
这样一个pooled-connection-factory的配置分3步完成,我引用:
创建一个指向远程消息服务器的出站套接字绑定: /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=remote-artemis:add(host=, port=61616)
创建一个远程连接器,引用在步骤 (1) 中创建的出站套接字绑定。 /subsystem=messaging-activemq/server=default/remote-connector=remote-artemis:add(socket-binding=remote-artemis)
创建一个池连接工厂,引用在步骤 (2) 中创建的远程连接器。 /subsystem=messaging-activemq/server=default/pooled-connection-factory=remote-artemis:add(connectors=[remote-artemis], 条目=[java:/jms/remoteCF])
最后,一旦正确配置了池连接工厂,就可以将其用作 JEE 容器可用的任何 JNDI 资源。 只需将池连接工厂注入您的 bean 并使用它来创建会话。
这里有一个关于如何将 JMS 消息发送到服务器的示例。 在您的情况下,只需将连接工厂 JNDI 引用修复到与远程活动 MQ 关联的池连接工厂。
http://www.mastertheboss.com/jboss-server/jboss-jms/sending-jms-messages-over-xa-with-wildfly-jboss-as
我引用:
@Stateless
public class JMSService
@Resource(mappedName = "java:jboss/jms/queue/exampleQueue")
private Queue queueExample;
@Resource(mappedName = "java:/JmsXA")
private ConnectionFactory cf;
private Connection connection;
private MessageProducer publisher;
private Session session;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void sendMessage(String txt)
try
connection = cf.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
publisher = session.createProducer(queueExample);
connection.start();
TextMessage message = session.createTextMessage(txt);
publisher.send(message);
catch (Exception exc)
exc.printStackTrace();
finally
if (publisher != null) try publisher.close(); catch (Exception ignore)
if (session != null) try session.close(); catch (Exception ignore)
if (connection != null) try connection.close(); catch (Exception ignore)
在这种情况下,您的连接工厂应该:
@Inject
@JMSConnectionFactory("java:/jms/remoteCF")
private JMSContext context;
您需要注意的另一件事是,您要注入 bean 的队列是远程队列。 访问远程队列的方法是在远程活动 MQ 服务器上执行 JNDI 查找。 这在这里解释。 http://activemq.apache.org/artemis/docs/1.1.0/using-jms.html#jndi-configuration
我引用文档中有趣的部分开始。如果您继续阅读,您会看到如何使用 JNDI 初始上下文来查找 artemis 队列。
如果客户端想将此队列绑定到“queues/OrderQueue” 那么 JNDI 属性将像这样配置:
java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory java.naming.provider.url=tcp://myhost:5445 queue.queues/OrderQueue=OrderQueue
还可以查找尚未访问过的 JMS 目的地 在 JNDI 上下文环境中显式配置。这是 可以在查找字符串中使用 dynamicQueues/ 或 dynamicTopics/。 例如,如果客户想要查找上述 “OrderQueue” 它可以简单地通过使用字符串来做到这一点 “动态队列/订单队列”。请注意,dynamicQueues/ 后面的文本 或 dynamicTopics/ 必须与 服务器上的目的地。
请仔细阅读有关此的 artemis 配置。
最后,您可以尝试探索另一种方法。 这些是 JMS 队列桥。 你太谷歌了。 但本质上,JMS 网桥可以允许队列的内容通过隧道传输到远程队列。 因此,这种桥接机制应该使您可以像针对本地 artemis JMS 服务器一样对代码进行编程,但是所有队列都被桥接,正在读取或发布的数据实际上来自或去往远程服务器。
但你必须了解自己,看看什么最适合你。
我真诚地希望这会有所帮助。
【讨论】:
始终欢迎提供指向潜在解决方案的链接,但请add context around the link,以便您的其他用户知道它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。考虑到仅仅是指向外部站点的链接是Why and how are some answers deleted? 的一个可能原因。 Uau!严重地?该 URL 称为:将池化 JMS 连接工厂连接到远程 Artemis 服务器。他的问题是如何连接到远程 Active MQ 服务器。你想让我解释一下完整的文档吗? “总是引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。” 为指出桥接方法而竖起大拇指,因为在我看来这似乎是一种更合适的方法。而不是更改我的 MDB(根据 STANDARD JMS 不会真正发生),而只是更改了设置。【参考方案2】:本周我一直在努力解决一个非常相似的问题。由于我的架构,我选择了一种您可能会觉得有用的替代方法:
继续向本地 Artemis 代理发送消息,但在 Artemis 代理和远程 ActiveMQ 代理之间配置 JMS 桥。
这种方法仍然让我有些头疼,但最后我让它运行良好。详情在:
JMS Bridge Between WildFly 10 Artemis and ActiveMQ 5.14 (ONCE_AND_ONLY_ONCE Quality of Service)
【讨论】:
我后来选择了不同的解决方案。我使用了 ActiveMQ 资源适配器,它像普通的战争文件一样部署到服务器。不是我会喜欢的解决方案,但很好,它奏效了。 @SayoOladeji ,您能否详细说明您的解决方案?我问了一个和你差不多的问题***.com/questions/43179283/…以上是关于如何将 JMS 消息从 WildFly 10 发送到远程 ActiveMQ的主要内容,如果未能解决你的问题,请参考以下文章
将JMS消息从Java EE应用程序发送到Java SE应用程序
Wildfly 上的 JMS 2.0 QueueBrowser 不返回消息