极大的ActiveMQ部署性能问题

时间:2016-02-02 00:57:35

标签: performance activemq message-queue spring-jms

我们计划部署一个ActiveMQ服务器场,该服务器场支持跨多个服务器的400多万个并发连接。我们没有使用基于我们设计的聚类。客户端使用MQTT进行连接,并从自己的主题进行订阅/使用,并发布到共享的虚拟主题。我们考虑的是每台服务器100k连接和20k msg / s。我无法达到这个数额。我成功地连接了这个数量,但是它的吞吐量让我受伤。

为了测试,我使用的是基于FuseSource MQTT客户端的Async(回调而非未来)版本的多线程客户端。使用该客户端,我能够在系统上加载足够的负载,以便我看到队列积压。我正在使用“java -jar activemq-all-5.13.0.jar dstat”获取队列积压。

我在很多方面调整了服务器,但无法利用所有资源。 Iostat显示低%util,top显示可用的cpu资源。

我的服务器在AWS m3.2xlarge(8vCPU,30G ram)上运行。

我正在使用“java -Xms12G -Xmx20G -jar ...”启动activemq

以下是我启动经纪人的方式。请注意,我已经更改了许多设置,但它们似乎并不重要。

@Bean
public BrokerService getBrokerService() throws Exception {
    String hostname= InetAddress.getLocalHost().getHostName();

    // Create broker
    BrokerService broker = new BrokerService();
    broker.setBrokerName("ActiveMQ"+hostname);
    broker.setUseShutdownHook(true);
    broker.setAdvisorySupport( false );
    broker.setUseJmx(true);
    broker.setDeleteAllMessagesOnStartup( true );
    broker.setPopulateJMSXUserID( true );
    broker.setPopulateUserNameInMBeans( true );
    broker.setUseAuthenticatedPrincipalForJMSXUserID( true );
    broker.setUseVirtualTopics( true );

    // I have altered these but they don't seem to change anything.
    broker.setDedicatedTaskRunner( true );
    broker.setEnableStatistics( true );
    broker.setStartAsync( true );

    // Enable JMX bean
    final ManagementContext managementContext = new ManagementContext();
    managementContext.setCreateConnector(true);
    broker.setManagementContext( managementContext );        

    // Enable LevelDB
    broker.setPersistent( true );
    File dataFileDir = new File("/activemq/data/leveldb);
    LevelDBStore adapter = new LevelDBStore();
    adapter.setDirectory(dataFileDir);
    broker.setPersistenceAdapter(adapter);

    // Turn flow control off
    PolicyEntry policy = new PolicyEntry();
    policy.setOptimizedDispatch( true );
    policy.setProducerFlowControl( false );
    policy.setGcInactiveDestinations( true );
    DispatchPolicy dp = new RoundRobinDispatchPolicy();
    policy.setDispatchPolicy( dp );
    PolicyMap policyMap = new PolicyMap();
    policyMap.setDefaultEntry( policy );
    broker.setDestinationPolicy( policyMap );

     // Set system usage
    SystemUsage memoryManager = new SystemUsage();
    MemoryUsage memoryUsage = new MemoryUsage();
    memoryUsage.setPercentOfJvmHeap( 75 );
    memoryManager.setMemoryUsage( memoryUsage );

    StoreUsage storeUsage = new StoreUsage();
    storeUsage.setLimit( 100*ONE_GB );
    memoryManager.setStoreUsage( storeUsage );

    TempUsage tempDiskUsage = new TempUsage();
    tempDiskUsage.setLimit( 100*ONE_GB );
    memoryManager.setTempUsage( tempDiskUsage );
    broker.setSystemUsage( memoryManager );

    // Add transports
    TransportConnector openwireconnector = new TransportConnector();
    openwireconnector.setName( "openwire" );
    openwireconnector.setUri(new URI("tcp://0.0.0.0:61616"));
    broker.addConnector(openwireconnector);

    TransportConnector mqttnioconnector = new TransportConnector();
    mqttnioconnector.setName( "mqtt+nio" );
    mqttnioconnector.setUri(new URI("mqtt+nio://0.0.0.0:1883"));
    broker.addConnector(mqttnioconnector);

    TransportConnector wsconnector = new TransportConnector();
    wsconnector.setName( "ws" );
    wsconnector.setUri(new URI("ws://0.0.0.0:61614"));
    broker.addConnector(wsconnector);

    // Start
    broker.start();
    broker.waitUntilStarted();
   return broker;
   }
}

我在连接到ActiveMQ的另一台服务器上使用spring JMS侦听器。

@Component
public class MqttMessageListener {
    @JmsListener(destination = "Consumer.A.VirtualTopic.Message")
    public void processMessage(BytesMessage bytesMessage) {
     // I consume and discard here just for testing.  No work is being done to isolate issue.    
    }
}

@Configuration
@EnableJms
public class AppConfig {
    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory) {
       DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setConcurrency(“3-10”);  // I have tried many variation including 300-1000 although it seems to top out at 500.
    factory.setAutoStartup( true );
    return factory;
    }
}

使用上面的MqttMessageListener.processMessage方法,我只能消耗大约15k msgs / sec。由于30%以上的CPU空闲和低磁盘/网络利用率,我不确定为什么我不能做得更好。

问题:

  1. 如何找到限制资源?
  2. 他们是一个简单的方法来确定这是ActiveMQ交付或消费方面的问题吗?两者都是Spring Boot应用程序。

0 个答案:

没有答案