发出或混淆JMS / spring / AMQ不是异步处理消息

时间:2012-10-18 17:20:32

标签: spring jms activemq jmstemplate

我们有一种情况,我们设置一个组件来远程使用spring批处理运行批处理作业。我们发送带有作业xml路径,名称,参数等的JMS消息,然后我们在调用批处理客户端上等待来自服务器的响应。

服务器读取队列并调用适当的方法来运行作业并返回结果,我们的消息传递框架通过它来执行:

    this.jmsTemplate.send(queueName, messageCreator);
    this.LOGGER.debug("Message sent to '" + queueName + "'");

    try {
        final Destination replyTo = messageCreator.getReplyTo();
        final String correlationId = messageCreator.getMessageId();

        this.LOGGER.debug("Waiting for the response '" + correlationId + "' back on '" + replyTo + "' ...");
        final BytesMessage message = (BytesMessage) this.jmsTemplate.receiveSelected(replyTo, "JMSCorrelationID='"
                + correlationId + "'");
        this.LOGGER.debug("Response received");

理想情况下,我们希望能够两次调用runJobSync方法,并同时运行两个作业。我们有一个单元测试做类似的事情,没有工作。我意识到这段代码不是很好,但是,这里是:

final List result = Collections.synchronizedList(new ArrayList());

    Thread thread1 = new Thread(new Runnable(){

        @Override
        public void run() {
            client.pingWithDelaySync(1000); 
            result.add(Thread.currentThread().getName());
        }

    }, "thread1");

    Thread thread2 = new Thread(new Runnable(){

        @Override
        public void run() {
            client.pingWithDelaySync(500);              
            result.add(Thread.currentThread().getName());
        }

    }, "thread2");

    thread1.start();
    Thread.sleep(250);
    thread2.start();

    thread1.join();
    thread2.join();

    Assert.assertEquals("both thread finished", 2, result.size());
    Assert.assertEquals("thread2 finished first", "thread2", result.get(0));
    Assert.assertEquals("thread1 finished second", "thread1", result.get(1));

当我们运行该测试时,线程2首先完成,因为它只有500毫秒的等待,而线程1则等待1秒:

Thread.sleep(delayInMs);
    return result;

这很有效。 当我们在野外运行两个远程作业时,一个需要大约50秒才能完成,一个被设计为立即失败并返回,这不会发生。

启动50秒作业,然后立即启动即时失败作业。客户端打印出我们发送的请求作业运行的消息,服务器打印出它接收到50秒的请求,但是等到50秒的作业完成后才处理第二条消息,即使我们使用的是ThreadPoolExecutor。 / p>

我们正在使用自动确认运行事务处理。

进行一些远程调试时,来自AbstractPollingMessageListenerContainer的Consumer不会显示任何未处理的消息(因此,consumer.receive()显然只是一遍又一遍地返回null)。 amq代理的webgui在调度队列中显示2个队列,1个双端队列,1个调度队列和1个队列。这告诉我,有些事情阻止了AMQ让消费者“拥有”第二条消息。 (预取是1000 btw) 这显示为特定队列的唯一消费者。

我自己和其他一些开发人员在过去的几天里一直在寻找并且几乎无处可去。关于这两者的任何建议,如果这是预期的行为我们错误配置了什么,或者在这里会被打破什么。

远程调用的方法是否重要?目前,作业处理程序方法使用执行程序在另一个线程中运行作业,并执行future.get()(额外的线程是出于与日志记录相关的原因)。

非常感谢任何帮助

1 个答案:

答案 0 :(得分:0)

不确定我是否完全遵循,但是从顶部开始,您应该尝试以下内容......

  • 将concurrentConsumers / maxConcurrentConsumers设置为大于MessageListenerContainer上的默认值(1)
  • 将预取设置为0以更好地促进消费者之间的消息平衡等。