使用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);
}
}
解決方式:
- 保證客戶端的id不重複
目前前端使用stomp連接時,採用了時間戳作爲client-id:如果同時有2個用戶連接,會出現衝突的問題
CONNECT
login:xxx
passcode:xxx
client-id:1589422159863
accept-version:1.1,1.0
heart-beat:10000,10000
- 允許盜鏈,修改mq配置:
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600&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秒的的隊列。
這個修改:可以讓管理界面流暢;也能緩解內存溢出問題