如何使用独占使用者设置Wildfly集群式JMS(apachemq)队列

时间:2018-07-25 09:51:49

标签: java jms activemq wildfly cluster-computing

如何在集群环境中设置wildfly jms消息以正确地在同一组中传递消息?
我已经找到了activeMq的属性,它可以解决此问题here,但是现在我不知道如何将其应用于wildfly的jms子系统。如何设置队列或Mdb在独占模式下工作?

我试图通过jms生产者将标志设置为“ exclusive?= true”,例如:

@Inject
private JMSContext context;

@Resource(mappedName = "java:/jms/queue/TestQueue?consumer.exclusive=true")
private Queue testQueue;

public void pushToQueue(String messagePayload, String messageGroup) {
try {
    Message message = context.createTextMessage(messagePayload);
    message.setStringProperty("JMSXGroupID", messageGroup);
    context.createProducer().send(processQueue, message);
} catch (JMSException e) {
    e.printStackTrace();
}

以及其他类似方式:

@Resource(name="DefaultJMSConnectionFactory")
private ConnectionFactory connectionFactory;

try {
    Connection connection = connectionFactory.createConnection();
    Session  session = connection.createSession();
    Queue queue = session.createQueue("TestQueue?consumer.exclusive=true");
    Message message = session.createTextMessage(messagePayload);
    session.createProducer(queue).send(message);
} catch (JMSException e) {
    e.printStackTrace();
}

在Mdb方面:

@MessageDriven(name = "queueMDB", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/queue/TestQueue?consumer.exclusive=true"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "5"),
})
public class ConsumerMdb implements MessageListener {
    ...
}

一切都没有成功。在这种情况下,我无法将字符串pf队列名称解析为URl参数,而是整个字符串表示队列名称(或JNI名称)

比起尝试使用'ActiveMQQueue'类来创建队列对象(该对象实现javax.jms.Destination的接口) 代码:

public void pushToQueue(String messagePayload, String messageGroup) {
    try {
        Connection connection = connectionFactory.createConnection();
        Session  session = connection.createSession();
        ActiveMQQueue queue = new ActiveMQQueue("TestQueue?consumer.exclusive=true");
        //ActiveMQQueue queue = new ActiveMQQueue("jms.queue.TestQueue");
        Message message = session.createTextMessage(messagePayload);
        session.createProducer(queue).send(message);
    } catch (JMSException e) {
        e.printStackTrace();
    }
}

在队列名称可能不同的情况下:

ActiveMQQueue queue = new ActiveMQQueue("TestQueue");

ActiveMQQueue queue = new ActiveMQQueue("TestQueue?consumer.exclusive=true");

ActiveMQQueue queue = new ActiveMQQueue("java:/jms/queue/TestQueue");

ActiveMQQueue queue = new ActiveMQQueue("jms.queue.TestQueue");

也成功了。我遇到了InvalidDestinationException:

12:54:12,959 ERROR [stderr] (default task-37) javax.jms.InvalidDestinationException: Not an ActiveMQ Artemis Destination:queue://TestQueue
12:54:12,959 ERROR [stderr] (default task-37)   at org.apache.activemq.artemis.jms.client.ActiveMQSession.createProducer(ActiveMQSession.java:293)
12:54:12,959 ERROR [stderr] (default task-37)   at org.apache.activemq.artemis.ra.ActiveMQRASession.createProducer(ActiveMQRASession.java:1082)
12:54:12,959 ERROR [stderr] (default task-37)   at si.teletech.test.eecluster.ejb.queue.Producer.pushToQueue(Producer.java:67)
12:54:12,960 ERROR [stderr] (default task-37)   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
12:54:12,960 ERROR [stderr] (default task-37)   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
12:54:12,960 ERROR [stderr] (default task-37)   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
12:54:12,960 ERROR [stderr] (default task-37)   at java.lang.reflect.Method.invoke(Method.java:498)
12:54:12,960 ERROR [stderr] (default task-37)   at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
12:54:12,960 ERROR [stderr] (default task-37)   at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
12:54:12,960 ERROR [stderr] (default task-37)   at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:509)
12:54:12,960 ERROR [stderr] (default task-37)   at org.jboss.as.weld.interceptors.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:90)
...

但是在例外情况下,我注意到队列名称已正确解析,没有URL参数。“ Destination:queue:// TestQueue”。

1 个答案:

答案 0 :(得分:0)

好吧,我自己以某种方式解决了它。我需要集群式单例交付。它的工作方式类似于独家消费者。 Mdb bean部署在群集服务器的所有节点上,但只有一个处于活动状态(消耗消息)。万一节点发生故障,Mdb将在链中的下一个节点上启动(即故障转移)。

@MessageDriven(name = "queueMDB", activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "TestQueue"),
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "5"),
    })
@ClusteredSingleton
public class ConsumerMdb implements MessageListener {
    // your mdb implementation
}

参考:https://docs.jboss.org/author/display/WFLY10/Message+Driven+Beans+Controlled+Delivery