Activemq - превышено максимально допустимое количество клиентских подключений

1

Мой сервер acitvemq всегда печатает ошибку ниже:

2014-07-12 16:14:27,820 | ERROR | Could not accept connection : 
org.apache.activemq.transport.tcp.ExceededMaximumConnectionsException:
Exceeded the maximum number of allowed client connections.
See the 'maximumConnections' property on the TCP transport configuration URI 
in the ActiveMQ configuration file (e.g., activemq.xml) 
| org.apache.activemq.broker.TransportConnector 
| ActiveMQ Transport Server Thread Handler:
 tcp://0.0.0.0:61616?maximumConnections=1000&wireformat.maxFrameSize=104857600

Когда я перезапущу сервер, все будет в порядке. Но через несколько дней снова появляется ошибка. Я не понимаю, почему соединения всегда увеличиваются до 1000.

Моя конфигурация сервера:

<!-- activeMQ -->
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="${jms.brokerURL}"></property>
</bean>

<!-- Spring Caching  -->
<bean id="cachingConnectionFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="targetConnectionFactory" ref="jmsConnectionFactory" />
    <property name="sessionCacheSize" value="10" />
</bean>

<!-- Spring JMS Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="cachingConnectionFactory" />
    <property name="explicitQosEnabled" value="true" />
    <property name="priority" value="4" />
</bean>

<bean id="scoreQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="SCORE" />
</bean>

<bean id="scoreMessage" class="com.tt.score.mq.server.ScoreMessage"></bean>

<bean id="scoreListener"
    class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="jmsConnectionFactory"></property>
    <property name="destination" ref="scoreQueue"></property>
    <property name="messageListener" ref="scoreMessage"></property>
    <property name="concurrentConsumers" value="10" />
    <property name="maxConcurrentConsumers" value="100" />
    <property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE" />
</bean>

Моя клиентская конфигурация xml:

<!-- Spring Caching -->
<bean id="cachingConnectionFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="targetConnectionFactory" ref="jmsConnectionFactory" />
    <property name="sessionCacheSize" value="10" />
</bean>

<!-- Spring JMS Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="cachingConnectionFactory" />
    <property name="explicitQosEnabled" value="true" />
    <property name="priority" value="4" />
</bean>

<bean id="messageProducer" class="com.tt.score.mq.client.MessageProducer">
    <property name="jmsTemplate" ref="jmsTemplate" />
    <property name="scoreQueue" ref="scoreQueue" />
</bean>

<bean id="scoreQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="SCORE" />
</bean>

Дополнительная информация:

  • Сервер acitvemq: 5.8.0
  • клиент acitvemq: 5.4.2
  • весна: 3,0,7
  • spring-jms: 3.0.7

Мы используем transactionManager, поэтому для кеша DefaultMessageListenerContainer будет установлено значение none.

---update добавить dao config----------------------------------

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"><value>${jdbc.driverClass}</value></property>
        <property name="username"><value>${jdbc.user}</value></property>
        <property name="url"><value>${jdbc.jdbcUrl}</value></property>
        <property name="password">
            <bean class="com.tongbanjie.commons.util.EncryptDBPasswordFactory">
                <property name="password" value="${jdbc.password}" />
            </bean>
        </property>
        <property name="maxActive"><value>${jdbc.maxActive}</value></property>
        <property name="initialSize"><value>${jdbc.initialSize}</value></property>
        <property name="maxWait"><value>60000</value></property>
        <property name="maxIdle"><value>${jdbc.maxIdle}</value></property>
        <property name="minIdle"><value>5</value></property>
        <property name="removeAbandoned"><value>true</value></property>
        <property name="removeAbandonedTimeout"><value>180</value></property>
        <property name="timeBetweenEvictionRunsMillis"><value>60000</value></property>
        <property name="minEvictableIdleTimeMillis"><value>1800000</value></property>
        <property name="defaultAutoCommit" value="false" />
        <property name="connectionProperties">
            <value>bigStringTryClob=true;clientEncoding=UTF-8;defaultRowPrefetch=50;serverEncoding=ISO-8859-1</value>
        </property>
    </bean>

    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />


    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
    </bean>

    <!-- myBatis -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:META-INF/mybatis/score-configuration.xml" />
        <property name="mapperLocations" value="classpath*:META-INF/mybatis/mapper/*.xml" />
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="commonSqlSessionDao" abstract="true">
        <property name="sqlSessionFactory">
            <ref bean="sqlSessionFactory" />
        </property>
    </bean>

-----post код, в котором мы, как использовать шаблон сейчас

jmsTemplate, завернутый в класс

public class MessageProducer {

    private JmsTemplate   jmsTemplate;
    private ActiveMQQueue scoreQueue;

    public void sendScoreQueue(Map<String, String> userMap) {
        sendMessage(this.scoreQueue, userMap);
    }

    private void sendMessage(Destination destination, final Map<String, String> map) {
        this.jmsTemplate.send(destination, new MessageCreator() {

            public Message createMessage(Session session) throws JMSException {
                MapMessage message = session.createMapMessage();
                for (String key : map.keySet()) {
                    message.setStringProperty(key, (String) map.get(key));
                }
                return message;
            }
        });
    }
}

И мы используем THEAD отправить вызвать MessageProducer класса sendScoreQueue метод. Следующим образом:

 //the code is old and ugly.that is the original position we call the mq.
 ThreadUtils.execute(new Thread(new SendMsgThread(dycc, ScoreMQSendType.SEND_TYPE_SCORE)));

///

public class ThreadUtils {

    protected static ThreadPoolExecutor executor = null;
    public static Properties            Props    = null;

    public static void execute(Thread thread) {
        executor.execute(thread);
    }

  static {
        if (executor == null) 
            Integer corePoolSize = 5;
            Integer maximumPoolSize = 10;
            Integer keepAliveTime = 3000;
            executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES,
                                              new LinkedBlockingQueue());
    }
}

public class SendMsgThread implements Runnable {

    private Log                    log      = LogFactory.getLog(SendMsgThread.class);

    private Map<String, String>    map;
    private String                 type;

    private static MessageProducer producer = null;

    public SendMsgThread(Map<String, String> map, String type){
        this.type = type;
        this.map = map;
    }

    public void run() {
        try {
            if(type.equals(ScoreMQSendType.SEND_TYPE_SCORE) || type.equals(ScoreMQSendType.SEND_TYPE_REGISTER)) {
                producer.sendMessage(map);
            }
        } catch (Exception e) {
            this.log.error("sendMsgThread sendScoreQueue error.", e);
        }
    }

 static {
        if (producer == null) producer = 
(MessageProducer )SpringContextHolder.getBean(MessageProducer .class);
    }
}
  • 0
    Вы говорите так: «Мы используем транзакциюManager, поэтому уровень кэша DefaultMessageListenerContainer будет установлен равным none». Ваш менеджер tx не является JmsTransactionManager, и DMLC не имеет своего свойстваactionManager.
  • 0
    Вы используете jmsConnectionFactory где-то еще в вашем приложении? Кроме того, как вы используете jmsTemplate , вы можете опубликовать код?
Показать ещё 18 комментариев
Теги:
spring
activemq
jms

2 ответа

0

У меня была та же проблема, повторяющаяся с той же ошибкой, и решение было получено в результате проб и ошибок, используйте jms-вызов для одновременных потребителей max до 101, а не 100, и посмотрите, повторяются ли результаты, добавив больше к значению, код, выполняемый далее в отладчике, вы достигнете значения при работе кода. Также решение, похоже, использует фабрику пулов соединений.

Попробуйте это, надеюсь, что это сработает, остальное моя реализация такая же, как ваша в bean файле

0

Для этого сценария вы должны использовать PooledConnectionFactory вместо cachingConnectionFactory. Более подробную информацию можно найти здесь. Разницу между ними можно найти здесь

Ещё вопросы

Сообщество Overcoder
Наверх
Меню