{"record":{"id":"5f2725ae666a9b71","repo":"YunaiV/ruoyi-vue-pro","slug":"error-5f2725","errorCode":null,"errorMessage":"连接数已达上限: {}","messagePattern":"连接数已达上限: (.+?)","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"warning","filePath":"yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/manager/IotTcpConnectionManager.java","lineNumber":55,"sourceCode":"     * 设备 ID -> NetSocket 的映射\n     */\n    private final Map<Long, NetSocket> deviceSocketMap = new ConcurrentHashMap<>();\n\n    public IotTcpConnectionManager(int maxConnections) {\n        this.maxConnections = maxConnections;\n    }\n\n    /**\n     * 注册设备连接（包含认证信息）\n     *\n     * @param socket         TCP 连接\n     * @param deviceId       设备 ID\n     * @param connectionInfo 连接信息\n     */\n    public synchronized void registerConnection(NetSocket socket, Long deviceId, ConnectionInfo connectionInfo) {\n        // 检查连接数是否已达上限（同步方法确保检查和注册的原子性）\n        if (connectionMap.size() >= maxConnections) {\n            throw new IllegalStateException(\"连接数已达上限: \" + maxConnections);\n        }\n        // 如果设备已有其他连接，先清理旧连接\n        NetSocket oldSocket = deviceSocketMap.get(deviceId);\n        if (oldSocket != null && oldSocket != socket) {\n            log.info(\"[registerConnection][设备已有其他连接，断开旧连接，设备 ID: {}，旧连接: {}]\",\n                    deviceId, oldSocket.remoteAddress());\n            // 先清理映射，再关闭连接\n            connectionMap.remove(oldSocket);\n            oldSocket.close();\n        }\n\n        // 注册新连接\n        connectionMap.put(socket, connectionInfo);\n        deviceSocketMap.put(deviceId, socket);\n        log.info(\"[registerConnection][注册设备连接，设备 ID: {}，连接: {}，product key: {}，device name: {}]\",\n                deviceId, socket.remoteAddress(), connectionInfo.getProductKey(), connectionInfo.getDeviceName());\n    }\n","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/YunaiV/ruoyi-vue-pro/blob/0418084e222612af2fc1141f566af454f9236ab1/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/manager/IotTcpConnectionManager.java#L37-L73","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: register throws, killing the auth flow\nconnectionManager.registerConnection(socket, deviceId, info);\n\n// after: guard and reject gracefully\nif (connectionManager.size() >= maxConnections) {\n    log.warn(\"[auth][连接数已达上限, 拒绝新连接 deviceId={} ]\", deviceId);\n    socket.close();\n    return;\n}\nconnectionManager.registerConnection(socket, deviceId, info);","handlingStrategy":"validation","validationCode":"// before registering, check the cap and reject gracefully instead of throwing\npublic boolean canRegister() {\n    synchronized (this) {\n        return connectionMap.size() < maxConnections;\n    }\n}\n// caller:\nif (!connectionManager.canRegister()) {\n    log.warn(\"[auth][连接数已达上限 {}，拒绝新连接]\", maxConnections);\n    socket.close();\n    return;\n}","typeGuard":null,"tryCatchPattern":"// in the auth/register handler, catch the limit error and close the socket cleanly\ntry {\n    connectionManager.registerConnection(socket, deviceId, info);\n} catch (IllegalStateException e) {\n    log.warn(\"[register][连接数已达上限，拒绝 deviceId={}]\", deviceId);\n    socket.close();\n}","preventionTips":["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."],"tags":["tcp","connection-limit","iot"],"backgroundTag":null,"analyzedSha":"0418084e222612af2fc1141f566af454f9236ab1","analyzedAt":"2026-08-14T00:56:18.412Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}