简体   繁体   English

无法同时从ActiveMQ嵌入式代理消费

[英]Cannot concurrently consume from ActiveMQ embedded broker

I'm looking for a way to publish 10 messages to an ActiveMQ embedded broker and, at the same VM, concurrently consume they using JMS API. 我正在寻找一种将10条消息发布到ActiveMQ嵌入式代理的方法,并在同一VM上使用JMS API同时使用它们。

The code below has some kind of race, because sometimes it consumes 2, 4, 8 messages in parallel, and hangs until timeout at the latch.await call. 下面的代码具有某种竞争性,因为有时它会并行消耗2、4、8条消息,并在latch.await调用中挂起直到超时。

public final class ActiveMQJMSParallelTest {
    private static final Logger logger = LoggerFactory.getLogger(ActiveMQJMSParallelTest.class);
    private static final int numberOfMessages = 10;

    public static void main(final String[] args) throws Exception {
        final Properties props = new Properties();
        props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
        props.setProperty(Context.PROVIDER_URL, "vm://localhost?broker.persistent=false");
        props.setProperty("queue.parallelQueue", "parallelQueue");
        final Context jndiContext = new InitialContext(props);
        final ConnectionFactory connectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");
        final Destination destination = (Destination) jndiContext.lookup("parallelQueue");
        final Connection connection = connectionFactory.createConnection();
        Session session = null;
        try {
            session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
            final MessageProducer producer = session.createProducer(destination);
            for (int i = 0; i < numberOfMessages; i++) {
                final TextMessage message = session.createTextMessage();
                message.setText("This is message " + (i + 1));
                producer.send(message);
                logger.info("Produced message: {}", message);
            }
            session.commit();
        } finally {
            if (session != null)
                session.close();
        }

        final CountDownLatch latch = new CountDownLatch(numberOfMessages);
        final ExecutorService pool = Executors.newFixedThreadPool(numberOfMessages);
        for (int i = 0; i < numberOfMessages; i++) {
            pool.submit(new Runnable() {
                @Override public void run() {
                    try {
                        final Connection connection = connectionFactory.createConnection();
                        connection.start();
                        final Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
                        final Queue destination = session.createQueue("parallelQueue");
                        final MessageConsumer consumer = session.createConsumer(destination);
                        final Message received = consumer.receive();
                        logger.info("Consuming message: {}", received);
                        latch.countDown();
                        latch.await(1, TimeUnit.MINUTES);
                        logger.info("Consumed message: {}", received);
                        session.close();
                        connection.close();
                    } catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        latch.await(10, TimeUnit.MINUTES);
        jndiContext.close();
    }
}

Can somebody conjure working code for this task? 有人可以联想到此任务的工作代码吗?

If you want to ensure that each consumer gets a chance to grab one message at a time then you should use a prefetch value of zero so that the broker does not try and dispatch up to the prefetch limit for the first consumer and so on as they arrive. 如果要确保每个使用者有机会一次抓取一条消息,则应使用预取值为零,以便代理不会尝试为第一个使用者分配最高预取限制,依此类推。到达。

Have a look at how prefetch works on the documentation page. 文档页面上查看预取的工作方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM