使用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秒的的队列。
这个修改:可以让管理界面流畅;也能缓解内存溢出问题