После включения протокола STOMP (до этого был включен только протокол по умолчанию) на сервере Activemq он начал выходить из строя с ошибкой oom. У меня всего 1 клиент, использующий STOMP. Он может работать без сбоев в течение 1 недели или через сутки после перезапуска. Вот конфигурационный файл:

<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">

    <bean id="logQuery" class="io.fabric8.insight.log.log4j.Log4jLogQuery"
          lazy-init="false" scope="singleton"
          init-method="start" destroy-method="stop">
    </bean>

    <!--
        The <broker> element is used to configure the ActiveMQ broker.
    -->
    <broker useJmx="true" xmlns="http://activemq.apache.org/schema/core" brokerName="cms-mq" dataDirectory="${activemq.data}">

        <destinationInterceptors>
            <virtualDestinationInterceptor>
                <virtualDestinations>
                    <virtualTopic name="VirtualTopic.>" selectorAware="true"/>
                </virtualDestinations>
            </virtualDestinationInterceptor>
        </destinationInterceptors>

        <destinationPolicy>
            <policyMap>
              <policyEntries>
                <policyEntry topic=">" producerFlowControl="false">
                </policyEntry>
                <policyEntry queue=">" producerFlowControl="false">
                </policyEntry>
              </policyEntries>
            </policyMap>
        </destinationPolicy>

        <managementContext>
            <managementContext createConnector="false"/>
        </managementContext>
        <persistenceAdapter>
            <kahaDB directory="${activemq.data}/kahadb"/>
        </persistenceAdapter>
          <systemUsage>
            <systemUsage>
                <memoryUsage>
                    <memoryUsage percentOfJvmHeap="70" />
                </memoryUsage>
                <storeUsage>
                    <storeUsage limit="4 gb"/>
                </storeUsage>
                <tempUsage>
                    <tempUsage limit="4 gb"/>
                </tempUsage>
            </systemUsage>
        </systemUsage>

        <transportConnectors>
            <transportConnector name="auto" uri="auto+nio://0.0.0.0:61616?maximumConnections=1000&amp;auto.protocols=default,stomp"/>
        </transportConnectors>
        <shutdownHooks>
            <bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
        </shutdownHooks>

        <plugins>
          ... security plugins config...
        </plugins>

    </broker>

    <import resource="jetty.xml"/>

</beans>

Начальные аргументы:

/usr/java/default/bin/java -Xms256M -Xmx1G -Dorg.apache.activemq.UseDedicatedTaskRunner=false -XX:HeapDumpPath=/var/logs/heapDumps -XX:+HeapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote.port=8162 -Dcom.sun.management.jmxremote.rmi.port=8162 -Dcom.sun.management.jmxremote.password.file=/opt/apache-activemq-5.13.0//conf/jmx.password -Dcom.sun.management.jmxremote.access.file=/opt/apache-activemq-5.13.0//conf/jmx.access -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote -Djava.awt.headless=true -Djava.io.tmpdir=/opt/apache-activemq-5.13.0//tmp -Dactivemq.classpath=/opt/apache-activemq-5.13.0//conf:/opt/apache-activemq-5.13.0//../lib/ -Dactivemq.home=/opt/activemq -Dactivemq.base=/opt/activemq -Dactivemq.conf=/opt/apache-activemq-5.13.0//conf -Dactivemq.data=/opt/apache-activemq-5.13.0//data -jar /opt/activemq/bin/activemq.jar start

UPD: Из Eclipse MemoryAnalizer:

Leak Suspects
247,036 instances of "org.apache.activemq.command.ActiveMQBytesMessage", loaded by "java.net.URLClassLoader @ 0xc02e9470" occupy 811,943,360 (76.92%) bytes. 

81 instances of "org.apache.activemq.broker.region.cursors.FilePendingMessageCursor", loaded by "java.net.URLClassLoader @ 0xc02e9470" occupy 146,604,368 (13.89%) bytes.

UPD: до появления ошибки OOM в журнале есть несколько ошибок, например:

| ERROR | Could not accept connection from null: java.lang.IllegalStateException: Timer already cancelled. | org.apache.activemq.broker.TransportConnector | ActiveMQ BrokerService[cms-mq] Task-13707
| INFO  | The connection to 'null' is taking a long time to shutdown. | org.apache.activemq.broker.TransportConnection | ActiveMQ BrokerService[cms-mq] Task-13738

Буду признателен за любую помощь в его отладке. При необходимости может предоставить дополнительную информацию.

7
pomkine 11 Май 2016 в 13:11

2 ответа

Лучший ответ

Я проверил клиентский код (клиент Ruby Stomp) и обнаружил, что там был подзаголовок activemq.subscriptionName без заголовка подключения client-id. Когда вы устанавливаете заголовок подписки activemq.subscriptionName, это означает, что вы хотите, чтобы ваш подписчик был надежным. Но вы также должны установить заголовок подключения 'client-id', потому что в противном случае он создается автоматически. Когда заголовок client-id не установлен, возникает ситуация, когда брокер не может идентифицировать клиента по идентификатору клиента при повторном подключении. В результате появилось много автономных подписчиков на устойчивые темы, и сообщения накапливались для каждой ошибки client-id => OOM.

0
pomkine 24 Май 2016 в 10:30

Можно предположить, что вы наводняете брокера сообщениями от производителя через STOMP и, в конечном итоге, разрушаете память брокера. Вы отключили управление потоком производителя, что может привести к этому даже с клиентом JMS по умолчанию, и STOMP еще проще попасть в эту ситуацию, поскольку по умолчанию нет подтверждения, возвращающегося к производителю, чтобы разрешить механизм управления потоком , вы должны запрашивать квитанцию при каждой отправке, чтобы ее получить.

Чтобы отладить это, вам нужно начать изучать журналы вашего брокера, а также статистику назначения и использования через консоль или другой инструмент по вашему выбору, чтобы узнать, в каком состоянии находится брокер.

2
Tim Bish 11 Май 2016 в 17:59