简体   繁体   English

Activemq - 超过了允许的最大客户端连接数

[英]Activemq - Exceeded the maximum number of allowed client connections

My acitvemq server always print error below :我的 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

When I restart the server it will be ok.当我重新启动服务器时,它会正常。 But after a few days the error come out again.但是过了几天,错误又出来了。 I don't why the connections always increase to 1000.我不明白为什么连接总是增加到 1000。

My server config:我的服务器配置:

<!-- 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>

My client config xml:我的客户端配置 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>

Other info:其他信息:

  • acitvemq server : 5.8.0 acitvemq 服务器:5.8.0
  • client acitvemq : 5.4.2客户端 acitvemq:5.4.2
  • spring : 3.0.7弹簧:3.0.7
  • spring-jms : 3.0.7弹簧-jms:3.0.7

We use transactionManager so the DefaultMessageListenerContainer's cachelevel will be set to none.我们使用 transactionManager 因此 DefaultMessageListenerContainer 的缓存级别将设置为 none。

---update add 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 the code that we how to use the template now -----贴出我们现在如何使用模板的代码

the jmsTemplate wrapped in a class包裹在一个类中的 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;
            }
        });
    }
}

And we use a thead to send call the MessageProducer class's sendScoreQueue method.并且我们使用thead 来发送调用MessageProducer类的sendScoreQueue方法。 As follows:如下:

 //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);
    }
}

For this scenario you should use PooledConnectionFactory instead of cachingConnectionFactory.对于这种情况,您应该使用 PooledConnectionFactory 而不是 cachingConnectionFactory。 More information can be found here .The difference between them can be found here更多信息可以在这里找到。它们之间的区别可以在这里找到

I had the same problem recurring with same error, and the solution was obtained as a result of trial and error, use jms call to concurrent consumers max to 101, instead of 100, and see if results repeat, adding more to the value results the code executed further on debugger, you will reach a value when code works , Also the solution appears to be using a connection pool factory.我遇到了同样的问题,重复出现同样的错误,通过反复试验获得了解决方案,使用 jms 调用并发消费者最大为 101,而不是 100,然后查看结果是否重复,将更多的值添加到结果中在调试器上进一步执行的代码,您将在代码工作时达到一个值,而且该解决方案似乎正在使用连接池工厂。

Try this, hope it works, rest my implementation is same as yours in bean file试试这个,希望它有效,我的实现与你在 bean 文件中的实现相同

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

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