171 lines
6.0 KiB
C#

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using YunDa.Server.ISMSTcp.Configuration;
using YunDa.Server.ISMSTcp.Interfaces;
namespace YunDa.Server.ISMSTcp.Services
{
/// <summary>
/// 自动连接服务 - 负责程序启动时自动连接TCP服务端
/// </summary>
public class AutoConnectionService : BackgroundService
{
private readonly ILogger<AutoConnectionService> _logger;
private readonly ITcpClient _tcpClient;
private readonly ISMSServerConfiguration _config;
private Timer? _connectionCheckTimer;
private readonly ZzDataCacheContainerInit _zzDataCacheContainerInit;
public AutoConnectionService(
ILogger<AutoConnectionService> logger,
ITcpClient tcpClient,
IOptions<ISMSServerConfiguration> config,
ZzDataCacheContainerInit zzDataCacheContainerInit)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_tcpClient = tcpClient ?? throw new ArgumentNullException(nameof(tcpClient));
_config = config?.Value ?? throw new ArgumentNullException(nameof(config));
_zzDataCacheContainerInit = zzDataCacheContainerInit ?? throw new ArgumentNullException(nameof(zzDataCacheContainerInit));
zzDataCacheContainerInit.InitTcpService(_tcpClient);
}
/// <summary>
/// 执行自动连接服务
/// </summary>
/// <param name="stoppingToken">停止令牌</param>
/// <returns>执行任务</returns>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
if (!_config.EnableAutoConnect)
{
_logger.LogInformation("Auto connection is disabled in configuration");
return;
}
// 等待指定的延迟时间,让其他服务完全启动
_logger.LogInformation("Auto connection service starting in {Delay} seconds...",
_config.AutoConnectDelaySeconds);
await Task.Delay(TimeSpan.FromSeconds(_config.AutoConnectDelaySeconds), stoppingToken);
// 尝试初始连接
await AttemptInitialConnectionAsync(stoppingToken);
// 启动定期连接检查
StartConnectionHealthCheck(stoppingToken);
// 保持服务运行
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
catch (OperationCanceledException)
{
_logger.LogInformation("Auto connection service was cancelled");
}
catch (Exception ex)
{
_logger.LogError(ex, "Auto connection service encountered an error");
}
finally
{
_connectionCheckTimer?.Dispose();
}
}
/// <summary>
/// 尝试初始连接
/// </summary>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>连接任务</returns>
private async Task AttemptInitialConnectionAsync(CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("Attempting initial connection to {IP}:{Port}",
_config.ServerIP, _config.ServerPort);
await _tcpClient.ConnectAsync(_config.ServerIP, _config.ServerPort, cancellationToken);
if (_tcpClient.IsConnected)
{
_logger.LogInformation("Initial connection successful");
}
else
{
_logger.LogWarning("Initial connection failed, but reconnection mechanism should handle this");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during initial connection attempt");
}
}
/// <summary>
/// 启动连接健康检查
/// </summary>
/// <param name="cancellationToken">取消令牌</param>
private void StartConnectionHealthCheck(CancellationToken cancellationToken)
{
if (!_config.EnableConnectionRetry)
{
_logger.LogInformation("Connection health check is disabled");
return;
}
_logger.LogInformation("Starting connection health check with interval of 60 seconds");
_connectionCheckTimer = new Timer(async _ =>
{
if (cancellationToken.IsCancellationRequested) return;
try
{
await _tcpClient.EnsureConnectedAsync(cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during connection health check");
}
}, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
}
/// <summary>
/// 停止服务时的清理工作
/// </summary>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>停止任务</returns>
public override async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Auto connection service is stopping...");
_connectionCheckTimer?.Dispose();
_connectionCheckTimer = null;
await base.StopAsync(cancellationToken);
_logger.LogInformation("Auto connection service stopped");
}
/// <summary>
/// 释放资源
/// </summary>
public override void Dispose()
{
_connectionCheckTimer?.Dispose();
base.Dispose();
}
}
}