YunaiV/ruoyi-vue-pro · warning · IllegalStateException
连接数已达上限: {}
Error message
连接数已达上限: {} What it means
registerConnection() throws IllegalStateException when the number of registered TCP connections has reached maxConnections. The check (connectionMap.size() >= maxConnections) and the subsequent put run atomically because the whole method is synchronized, so the cap is enforced correctly. The exception propagates to the auth handler, typically rejecting the new device connection.
Source
Thrown at yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/manager/IotTcpConnectionManager.java:55
* 设备 ID -> NetSocket 的映射
*/
private final Map<Long, NetSocket> deviceSocketMap = new ConcurrentHashMap<>();
public IotTcpConnectionManager(int maxConnections) {
this.maxConnections = maxConnections;
}
/**
* 注册设备连接(包含认证信息)
*
* @param socket TCP 连接
* @param deviceId 设备 ID
* @param connectionInfo 连接信息
*/
public synchronized void registerConnection(NetSocket socket, Long deviceId, ConnectionInfo connectionInfo) {
// 检查连接数是否已达上限(同步方法确保检查和注册的原子性)
if (connectionMap.size() >= maxConnections) {
throw new IllegalStateException("连接数已达上限: " + maxConnections);
}
// 如果设备已有其他连接,先清理旧连接
NetSocket oldSocket = deviceSocketMap.get(deviceId);
if (oldSocket != null && oldSocket != socket) {
log.info("[registerConnection][设备已有其他连接,断开旧连接,设备 ID: {},旧连接: {}]",
deviceId, oldSocket.remoteAddress());
// 先清理映射,再关闭连接
connectionMap.remove(oldSocket);
oldSocket.close();
}
// 注册新连接
connectionMap.put(socket, connectionInfo);
deviceSocketMap.put(deviceId, socket);
log.info("[registerConnection][注册设备连接,设备 ID: {},连接: {},product key: {},device name: {}]",
deviceId, socket.remoteAddress(), connectionInfo.getProductKey(), connectionInfo.getDeviceName());
}
View on GitHub (pinned to 0418084e22)
Solutions
- Raise maxConnections to the expected concurrent device count (plus headroom) in the connection manager config.
- Verify every socket close path calls unregisterConnection/removeConnection so slots are freed — check closeHandler wiring in the protocol handler (e.g. IotTcpProtocol / Modbus TCP Server handleConnection).
- Catch the IllegalStateException in the auth/register path and respond to the device with a 'server busy' / retry-later instead of propagating.
- Monitor connectionMap.size() vs maxConnections and alert before saturation.
Example fix
// before: register throws, killing the auth flow
connectionManager.registerConnection(socket, deviceId, info);
// after: guard and reject gracefully
if (connectionManager.size() >= maxConnections) {
log.warn("[auth][连接数已达上限, 拒绝新连接 deviceId={} ]", deviceId);
socket.close();
return;
}
connectionManager.registerConnection(socket, deviceId, info); Defensive patterns
Strategy: validation
Validate before calling
// before registering, check the cap and reject gracefully instead of throwing
public boolean canRegister() {
synchronized (this) {
return connectionMap.size() < maxConnections;
}
}
// caller:
if (!connectionManager.canRegister()) {
log.warn("[auth][连接数已达上限 {},拒绝新连接]", maxConnections);
socket.close();
return;
} Try / catch
// in the auth/register handler, catch the limit error and close the socket cleanly
try {
connectionManager.registerConnection(socket, deviceId, info);
} catch (IllegalStateException e) {
log.warn("[register][连接数已达上限,拒绝 deviceId={}]", deviceId);
socket.close();
} Prevention
- Size maxConnections to the deployed fleet plus headroom.
- Ensure every close path calls unregisterConnection/removeConnection so stale sockets free their slots (audit closeHandler wiring).
- Monitor connectionMap.size() vs maxConnections and alert before saturation.
- Reject excess connections with a clear 'server busy' response rather than letting an exception propagate.
When it happens
Trigger: More than maxConnections devices connect and authenticate concurrently; maxConnections configured too low for the fleet; closed sockets are not unregistered (leak) so the map fills with stale entries; a device reconnect storm exceeds the cap.
Common situations: maxConnections under-provisioned vs deployed device count; a bug where closeHandler/unregisterConnection is missing so closed sockets leak slots; load test exceeding the configured ceiling.
Related errors
- [createProtocol][协议实例 %s 的协议类型 %s 暂不支持]
- MQTT Client 启动失败: 连接 Broker 失败
- Modbus 读取失败 [slaveId=%d, identifier=%s, functionCode=%d, add
- 功能码 {} 不支持写操作
- Modbus 写入失败 [slaveId=%d, identifier=%s, address=%d]
AI-assisted analysis of YunaiV/ruoyi-vue-pro@0418084e22 (2026-08-14).
Data as JSON: /api/errors/5f2725ae666a9b71.
Report an issue: GitHub.