修改重连逻辑

联合利华-拍照
LAPTOP-S9HJSOEB\昊天 4 weeks ago
parent 583d812e85
commit fd3ddb7fea

@ -109,6 +109,12 @@ public class S7MultiPlcService {
// 读取间隔(ms) // 读取间隔(ms)
private static final int READ_INTERVAL = 1000; private static final int READ_INTERVAL = 1000;
// 重连最大重试次数
private static final int RECONNECT_MAX_RETRIES = 5;
// 重连间隔(ms)
private static final int RECONNECT_INTERVAL = 3000;
// 线程池 // 线程池
private ExecutorService executorService; private ExecutorService executorService;
@ -189,10 +195,16 @@ public class S7MultiPlcService {
try { try {
S7Client client = pool.take(); S7Client client = pool.take();
if (!client.Connected) { if (!client.Connected) {
PlcData config = getPlcConfig(plcNumber); client.Disconnect();
if (config != null) { // 用带重试的方法重新连接
client.ConnectTo(config.getIp(), config.getRack(), config.getSlot()); S7Client newClient = reconnectWithRetry(plcNumber);
if (newClient != null) {
return newClient;
} }
// 重连失败把旧client放回虽然不可用至少不丢失池容量
log.warn("PLC {} 获取连接时重连失败", plcNumber);
pool.offer(client);
return null;
} }
return client; return client;
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -211,16 +223,45 @@ public class S7MultiPlcService {
if (client.Connected) { if (client.Connected) {
pool.offer(client); pool.offer(client);
} else { } else {
// 断开旧连接,尝试重连后放回池中
client.Disconnect();
S7Client newClient = reconnectWithRetry(plcNumber);
if (newClient != null) {
pool.offer(newClient);
} else {
log.warn("PLC {} 归还连接时重连失败,池中剩余: {}/{}", plcNumber, pool.size(), POOL_SIZE);
}
}
}
}
/**
*
* @return null
*/
private S7Client reconnectWithRetry(String plcNumber) {
PlcData config = getPlcConfig(plcNumber); PlcData config = getPlcConfig(plcNumber);
if (config != null) { if (config == null) return null;
for (int i = 1; i <= RECONNECT_MAX_RETRIES; i++) {
S7Client newClient = new S7Client(); S7Client newClient = new S7Client();
int result = newClient.ConnectTo(config.getIp(), config.getRack(), config.getSlot()); int result = newClient.ConnectTo(config.getIp(), config.getRack(), config.getSlot());
if (result == 0) { if (result == 0) {
pool.offer(newClient); log.info("PLC {} 重连成功(第{}次尝试)", plcNumber, i);
return newClient;
} }
log.warn("PLC {} 重连失败(第{}/{}次),错误码: {}", plcNumber, i, RECONNECT_MAX_RETRIES, result);
if (i < RECONNECT_MAX_RETRIES) {
try {
sleep(RECONNECT_INTERVAL);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
} }
} }
} }
log.error("PLC {} 重连失败,已达最大重试次数 {}", plcNumber, RECONNECT_MAX_RETRIES);
return null;
} }
/** /**
@ -313,9 +354,31 @@ public class S7MultiPlcService {
if (result != 0) { if (result != 0) {
log.error("PLC {} 读取失败,错误码: {}", plcNumber, result); log.error("PLC {} 读取失败,错误码: {}", plcNumber, result);
// 断开坏连接,防止僵尸连接被复用
client.Disconnect();
returnConnection(plcNumber, client); returnConnection(plcNumber, client);
// 重试一次
S7Client retryClient = getConnection(plcNumber);
if (retryClient != null) {
try {
byte[] retryBuffer = new byte[readLength];
int retryResult = retryClient.ReadArea(S7.S7AreaDB, config.getReadDataBlock(), 0, readLength, retryBuffer);
if (retryResult == 0) {
log.info("PLC {} 重试读取成功", plcNumber);
buffer = retryBuffer;
result = 0;
} else {
log.error("PLC {} 重试读取仍失败,错误码: {}", plcNumber, retryResult);
retryClient.Disconnect();
}
} finally {
returnConnection(plcNumber, retryClient);
}
}
if (result != 0) {
return readDataCache.get(plcNumber); return readDataCache.get(plcNumber);
} }
}
PlcReadData data = new PlcReadData(); PlcReadData data = new PlcReadData();
data.setPalletNo(readString(buffer, (int) config.getPalletOffset(), getDataTypeSize(config.getPalletDataType()))); data.setPalletNo(readString(buffer, (int) config.getPalletOffset(), getDataTypeSize(config.getPalletDataType())));
@ -648,6 +711,8 @@ public class S7MultiPlcService {
log.info("PLC {} 写入拍照结果成功: {}", plcNumber, photoResult); log.info("PLC {} 写入拍照结果成功: {}", plcNumber, photoResult);
} else { } else {
log.error("PLC {} 写入拍照结果失败,错误码: {}", plcNumber, result); log.error("PLC {} 写入拍照结果失败,错误码: {}", plcNumber, result);
// 断开坏连接,防止僵尸连接被复用
client.Disconnect();
} }
returnConnection(plcNumber, client); returnConnection(plcNumber, client);
return result == 0; return result == 0;
@ -704,6 +769,7 @@ public class S7MultiPlcService {
List<S7Client> clients = new ArrayList<>(); List<S7Client> clients = new ArrayList<>();
pool.drainTo(clients); pool.drainTo(clients);
// 1. 保留有效连接,清理无效连接
for (S7Client client : clients) { for (S7Client client : clients) {
if (client != null && client.Connected) { if (client != null && client.Connected) {
pool.offer(client); pool.offer(client);
@ -711,20 +777,25 @@ public class S7MultiPlcService {
if (client != null) { if (client != null) {
client.Disconnect(); client.Disconnect();
} }
PlcData config = getPlcConfig(plcNumber);
if (config != null) {
S7Client newClient = new S7Client();
int result = newClient.ConnectTo(config.getIp(), config.getRack(), config.getSlot());
if (result == 0) {
pool.offer(newClient);
cleaned++; cleaned++;
} }
} }
// 2. 补满连接池到POOL_SIZE带重试
int currentSize = pool.size();
for (int i = currentSize; i < POOL_SIZE; i++) {
log.info("PLC {} 连接池不足({}/{}),尝试补充...", plcNumber, currentSize, POOL_SIZE);
S7Client newClient = reconnectWithRetry(plcNumber);
if (newClient != null) {
pool.offer(newClient);
} else {
log.error("PLC {} 补充连接失败,当前池大小: {}/{}", plcNumber, pool.size(), POOL_SIZE);
break; // 重试都失败了,不再继续补
} }
} }
if (cleaned > 0) { if (cleaned > 0 || pool.size() < POOL_SIZE) {
log.info("PLC {} 替换了 {} 个无效连接", plcNumber, cleaned); log.info("PLC {} 清理{}个无效连接,当前池大小: {}/{}", plcNumber, cleaned, pool.size(), POOL_SIZE);
} }
} }
log.info("PLC连接池清理完成"); log.info("PLC连接池清理完成");

Loading…
Cancel
Save