ActiveMQ問題與調優

使用ActiveMq的問題。

javax.jms.InvalidClientIDException: Broker: localhost - Client: client-id

2020-05-13 08:58:53,108 | WARN | Failed to add Connection id=ID:host04-36868-1589330662649-3:7467, clientId=1589290606450 due to {} 
| org.apache.activemq.broker.TransportConnection | qtp1879414521-27691
javax.jms.InvalidClientIDException: Broker: localhost - Client: 1589290606450 already connected from ws://127.0.0.1:48030
at org.apache.activemq.broker.region.RegionBroker.addConnection(RegionBroker.java:247)[activemq-broker-5.15.9.jar:5.15.9]
at org.apache.activemq.broker.jmx.ManagedRegionBroker.addConnection(ManagedRegionBroker.java:227)[activemq-broker-5.15.9.jar:5.15.9]
at org.apache.activemq.broker.BrokerFilter.addConnection(BrokerFilter.java:99)[activemq-broker-5.15.9.jar:5.15.9]
at org.apache.activemq.advisory.AdvisoryBroker.addConnection(AdvisoryBroker.java:119)[activemq-broker-5.15.9.jar:5.15.9]
at org.apache.activemq.broker.BrokerFilter.addConnection(BrokerFilter.java:99)[activemq-broker-5.15.9.jar:5.15.9]
at org.apache.activemq.broker.BrokerFilter.addConnection(BrokerFilter.java:99)[activemq-broker-5.15.9.jar:5.15.9]
at org.apache.activemq.broker.BrokerFilter.addConnection(BrokerFilter.java:99)[activemq-broker-5.15.9.jar:5.15.9]

分析源碼(org.apache.activemq.broker.region.RegionBroker.addConnection)可知這個原因是由於客戶端的client-id重複,也就是盜鏈,但是我們沒有允許。

    synchronized (this.clientIdSet) {
      oldContext = this.clientIdSet.get(clientId);
      if (oldContext != null) {
        if (context.isAllowLinkStealing()) {
          this.clientIdSet.put(clientId, context);
        } else {
          throw new InvalidClientIDException("Broker: " + getBrokerName() + " - Client: " + clientId + " already connected from " + oldContext
              .getConnection().getRemoteAddress());
        } 
      } else {
        this.clientIdSet.put(clientId, context);
      } 
    }

解決方式:

  1. 保證客戶端的id不重複
    目前前端使用stomp連接時,採用了時間戳作爲client-id:如果同時有2個用戶連接,會出現衝突的問題
CONNECT
login:xxx
passcode:xxx
client-id:1589422159863
accept-version:1.1,1.0
heart-beat:10000,10000
  1. 允許盜鏈,修改mq配置:
<transportConnector  name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600&amp;allowLinkStealing=true"/>

java.lang.OutOfMemoryError: GC overhead limit exceeded

內存溢出是個很常見的問題,下面的問題是由於回收頻繁卻效果甚微。

2020-05-13 21:11:38,495 | WARN  | Transport Connection to: tcp://59.151.65.101:40204 failed: java.io.IOException: Unexpected error occurred: java.lang.OutOfMemoryError: GC overhead limit exceeded 
| org.apache.activemq.broker.TransportConnection.Transport | ActiveMQ Transport: tcp:///59.151.65.101:40204@61616

默認,activemq的jvm配置是最大1G內存, 根據/bin/activemq啓動腳本可以知道:

# System variables for this script, like ACTIVEMQ_OPTS and ACTIVEMQ_OPTS_MEMORY,
# can be configured in 'env' script located in this directory.

/bin/env裏可以看到配置:所以修改這裏就行

# Set jvm memory configuration (minimal/maximum amount of memory)
ACTIVEMQ_OPTS_MEMORY="-Xms64M -Xmx1G"

if [ -z "$ACTIVEMQ_OPTS" ] ; then
    ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS_MEMORY -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=$ACTIVEMQ_CONF/login.config"
fi

優化配置

定時移除過期的隊列

修改conf/activemq.xml:

    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" useJmx="true" dataDirectory="${activemq.data}"  schedulePeriodForDestinationPurge="60000">

        <destinationPolicy>
            <policyMap>
              <policyEntries>
                <policyEntry topic=">" >
                  <pendingMessageLimitStrategy>
                    <constantPendingMessageLimitStrategy limit="1000"/>
                  </pendingMessageLimitStrategy>
                </policyEntry>
				<policyEntry queue=">" gcInactiveDestinations="true" inactiveTimeoutBeforeGC="30000"/>
              </policyEntries>
            </policyMap>
        </destinationPolicy>
...

上面配置的是:每60秒清理一次,清理過期30秒的的隊列。

這個修改:可以讓管理界面流暢;也能緩解內存溢出問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章