如何从WildFly 10向远程ActiveMQ发送JMS消息。

7
在互联网上搜寻后,惊讶地发现找不到使用JMS在WildFly 10中推送到远程消息队列(ActiveMQ / Artemis)的配置示例。更糟糕的是, standalone-full.xml未绑定模式(为什么?),当我最终找到XSD文件(在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实例发布消息。

我拥有的: 服务器URL, 主题名称, 用户名密码

我的问题: 如何修改配置以达到此目的?

备选问题: 如果上述问题无法回答,我该如何达成这个目标?

谢谢!

2个回答

6
您是否查看了以下文档:https://docs.jboss.org/author/display/WFLY10/Connect+a+pooled-connection-factory+to+a+Remote+Artemis+Server,它可能解决您当前的问题。请按照文档中的说明进行操作,需要创建一个使用远程连接器的池化连接工厂,并且远程连接器引用远程Active MQ服务器的IP x Socket。配置此类池化连接工厂需要3个步骤,具体见上述文档。一旦您的池化连接工厂正确配置,您可以将其用作JEE容器中可用的任何JNDI资源。只需将池化连接工厂注入到您的bean中并使用它来创建会话即可。这里有一个向服务器发送JMS消息的示例,您只需要将连接工厂JNDI引用修复为与远程Active 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的队列是一个远程队列。要访问远程队列的方法是在远程 ActiveMQ 服务器上执行 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 ```
还可以查找未在 JNDI 上下文环境中明确配置的 JMS 目标。可以在查找字符串中使用 dynamicQueues/ 或 dynamicTopics/。例如,如果客户端想查找前面提到的 "OrderQueue",只需使用字符串 "dynamicQueues/OrderQueue" 即可。请注意,跟随 dynamicQueues/ 或 dynamicTopics/ 的文本必须与服务器上的目标名称完全对应。
请查看 Artemis 配置以了解更多信息。最后,还有另一种方法可以尝试探索,那就是 JMS 队列桥接。你需要自己 Google。但基本上,JMS 桥接可以允许队列的内容隧道到远程队列。因此,这种桥接机制应该为您提供了在本地 Artemis JMS 服务器上编写代码的可能性,但所有队列都被桥接,所以读取或发布的数据实际上来自或发送到远程服务器。但是,您必须自己了解哪种方法最适合您。我真诚地希望这可以帮助到您。

1
欢迎提供潜在解决方案的链接,但请添加链接周围的上下文,以便其他用户了解它是什么以及为什么存在。始终引用重要链接的最相关部分,以防目标站点无法访问或永久离线。请注意,仅仅是外部网站链接的答案可能是为什么和如何删除某些答案?的原因之一。 - FelixSFD
哇!真的吗?该URL称为:将池化的JMS连接工厂连接到远程Artemis服务器。他的问题是如何连接到远程Active MQ服务器。你想让我转述整个文档吗? - 99Sono
“始终引用重要链接的最相关部分,以防目标网站无法访问或永久下线。” - FelixSFD
谢谢你指出了桥接方法,这在我看来似乎是更合适的方式。而不是改变我的 MDB(根据 JMS 标准,这实际上不应该发生),只需要改变设置即可。 - mohamnag

0

这个星期我一直在为一个非常类似的问题苦苦挣扎。由于我的架构选择了一种替代方法,你可能会发现它很有用:

继续向本地 Artemis Broker 发送消息,但在 Artemis broker 和远程 ActiveMQ broker 之间配置一个 JMS-bridge。

这种方法仍然给我带来了一些头疼,但最终我成功地让它工作了。详情请见:

JMS Bridge Between WildFly 10 Artemis and ActiveMQ 5.14 (ONCE_AND_ONLY_ONCE Quality of Service)


后来我选择了另一种解决方案。我使用了ActiveMQ资源适配器,就像将常规war文件部署到服务器一样。虽然不是我最喜欢的解决方案,但它确实起作用了。 - Sayo Oladeji
@SayoOladeji,您能详细说明一下您的解决方案吗?我问了一个几乎与您相同的问题https://dev59.com/EKDia4cB1Zd3GeqPFpHl - webyildirim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接