P2: DeviceHealthMonitor 重连增加指数退避策略(3→5→7→...→15)

This commit is contained in:
“hsc”
2026-09-10 14:27:39 +08:00
parent bd1c25a67d
commit 2ddaf0e6f7
+22 -7
View File
@@ -34,8 +34,14 @@ namespace UIShare.GlobalVariable
/// <summary>每个设备的连续失败计数</summary>
private readonly ConcurrentDictionary<string, int> _failureCounts = new();
/// <summary>连续失败次数阈值,达到后触发重连</summary>
private const int FailureThreshold = 3;
/// <summary>每个设备的重连尝试次数(用于计算退避阈值)</summary>
private readonly ConcurrentDictionary<string, int> _reconnectAttempts = new();
/// <summary>基础失败阈值(首次重连触发值)</summary>
private const int BaseFailureThreshold = 3;
/// <summary>退避上限(最大阈值)</summary>
private const int MaxBackoffThreshold = 15;
/// <summary>健康检查间隔(毫秒)</summary>
private readonly int _checkIntervalMs;
@@ -73,7 +79,7 @@ namespace UIShare.GlobalVariable
null,
TimeSpan.FromSeconds(10), // 首次检查延迟 10 秒,避免启动时设备尚未连接完成
TimeSpan.FromMilliseconds(_checkIntervalMs));
LoggerHelper.Info($"[{_scopeName}] 设备健康监控已启动,检查间隔={_checkIntervalMs}ms,重连阈值={FailureThreshold}次");
LoggerHelper.Info($"[{_scopeName}] 设备健康监控已启动,检查间隔={_checkIntervalMs}ms基础重连阈值={BaseFailureThreshold}次(指数退避上限={MaxBackoffThreshold}");
}
}
@@ -86,6 +92,7 @@ namespace UIShare.GlobalVariable
_healthCheckTimer?.Dispose();
_healthCheckTimer = null;
_failureCounts.Clear();
_reconnectAttempts.Clear();
}
}
@@ -119,18 +126,23 @@ namespace UIShare.GlobalVariable
if (alive)
{
// 连接正常:清零失败计数
// 连接正常:清零失败计数与退避
_failureCounts.TryRemove(deviceName, out _);
_reconnectAttempts.TryRemove(deviceName, out _);
continue;
}
// 连接断开:累加失败计数
int failures = _failureCounts.AddOrUpdate(deviceName, 1, (_, count) => count + 1);
if (failures < FailureThreshold)
// 计算当前退避阈值:基础值 + 重连尝试次数 × 2,上限为 MaxBackoffThreshold
int attempts = _reconnectAttempts.GetOrAdd(deviceName, 0);
int currentThreshold = Math.Min(BaseFailureThreshold + attempts * 2, MaxBackoffThreshold);
if (failures < currentThreshold)
{
LoggerHelper.Warn(
$"[{_scopeName}] 设备 [{deviceName}] 连接断开,等待重连中 ({failures}/{FailureThreshold})");
$"[{_scopeName}] 设备 [{deviceName}] 连接断开,等待重连中 ({failures}/{currentThreshold})");
continue;
}
@@ -175,7 +187,9 @@ namespace UIShare.GlobalVariable
{
try
{
LoggerHelper.Info($"[{_scopeName}] 设备 [{deviceName}] 连续 {FailureThreshold} 次检测断连,开始重连...");
int attempts = _reconnectAttempts.AddOrUpdate(deviceName, 1, (_, c) => c + 1);
int nextThreshold = Math.Min(BaseFailureThreshold + attempts * 2, MaxBackoffThreshold);
LoggerHelper.Info($"[{_scopeName}] 设备 [{deviceName}] 连续失败触发重连(第 {attempts} 次重连,下次阈值={nextThreshold}...");
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
bool ok = await device.ConnectAsync(cts.Token);
@@ -186,6 +200,7 @@ namespace UIShare.GlobalVariable
if (ok)
{
_failureCounts.TryRemove(deviceName, out _);
_reconnectAttempts.TryRemove(deviceName, out _);
LoggerHelper.Info($"[{_scopeName}] 设备 [{deviceName}] 重连成功");
}
else