SJMS2 与 JMS 组件的对比,用于在 ActiveMQ Artemis 之间传输消息

SJMS2 vs JMS components for transfer messages from and to ActiveMQ Artemis

我正在尝试找到使用 Camel 将消息从一个 ActiveMQ Artemis 队列传输到另一个队列的最快方法。我认为 Camel 的 SJMS2 component would be faster than Camel's traditional JMS 组件,但使用 JMS 组件的路由速度快 2.5 倍(20,000 对 8,000 msg/s)。我使用 Camel 2.20.2 版和 Artemis 2.11.0 版。

使用 JMS 路由

import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.JndiRegistry;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;

import javax.jms.ConnectionFactory;
import java.util.concurrent.TimeUnit;

public class JMSTransferTest extends CamelTestSupport {
    @Test
    public void testArtemis() throws Exception {
        TimeUnit.SECONDS.sleep(100);
    }

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            public void configure() {
                from("jms://TEST.IN?connectionFactory=#artemisCF&concurrentConsumers=200")
                        .to("jms://TEST.OUT?connectionFactory=#artemisCF");
            }
        };
    }

    @Override
    protected JndiRegistry createRegistry() throws Exception {
        JndiRegistry registry = super.createRegistry();

        final ConnectionFactory connFactory = new ActiveMQConnectionFactory("tcp://localhost:61622");
        final ConnectionFactory connFactoryDeadLeatter = new ActiveMQConnectionFactory("tcp://localhost:61622");
        JmsPoolConnectionFactory pooledConnectionFactory = new JmsPoolConnectionFactory();

        pooledConnectionFactory.setConnectionFactory(connFactory);
        pooledConnectionFactory.setMaxConnections(20);
        pooledConnectionFactory.setMaxSessionsPerConnection(100);
        registry.bind("artemisCF", pooledConnectionFactory);
        registry.bind("deadLetterCF", connFactoryDeadLeatter);
        return registry;
    }
}

使用SJMS2路由,其他设置如上代码

@Override
protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        public void configure() {
            from("sjms2://TEST.IN?connectionFactory=#artemisCF&consumerCount=200&asyncStartListener=true")
                    .to("sjms2://TEST.OUT?connectionFactory=#artemisCF");
        }
    };
}

如何使用 SJMS2 组件获得与 JMS 组件相同的速度?

克劳斯·易卜生在邮件列表中回复如下

200 consumers is too much. That instead makes it slower as you have 200 consumers racing for messages. Instead try to find a lower balance that is closer to cpu cores etc.

Also often a JMS client has a prefetch buffer (or some concept like this) which means a consumer may pre-download 1000 messages and then the other 199 consumers cant process these messages. So you need to tweak this option too.

Also if you have too many consumers and remote network connections then you get too chatty over IO etc. So its all about tuning depending on use-cases.

spring-jms has a thread pool built in that can automatic grow/shrink depending on load, and this can explain why its out of the box without tuning can appear to be faster.

Writing such logic is a bit more complex and this hasnt been added to sjms. I created a ticket about this https://issues.apache.org/jira/browse/CAMEL-14637

You can get in touch with commercial Camel supports as there are companies and consultants that has great experience with JMS brokers and Camel and to get them tuned to very high performance. The settings for JVM and OS and hardware can all make a big difference.

而且我还找到了一篇关于这个主题的好文章https://dzone.com/articles/performance-tuning-ideas-for-apache-camel