using Serilog;
using System;
using System.Threading;
using System.Threading.Tasks;
using RunRedis.Services;
using RunRedis.Models;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.IO;
namespace RunRedis
{
public class EnhancedWorker
{
private readonly RedisSetting _settings;
private readonly RedisProcessManager _processManager;
private readonly CancellationTokenSource _cancellationTokenSource;
private bool _isRunning = false;
private DateTime _lastHealthCheck = DateTime.MinValue;
public EnhancedWorker(RedisSetting settings)
{
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
_processManager = new RedisProcessManager(_settings);
_cancellationTokenSource = new CancellationTokenSource();
}
public async Task ExecuteAsync()
{
_isRunning = true;
Log.Information("🚀 启动简化 Redis 监控服务");
try
{
// Simplified initial setup
await EnsureRedisRunningAsync();
// Start simplified monitoring loop
await SimplifiedMonitoringLoopAsync(_cancellationTokenSource.Token);
}
catch (Exception ex)
{
Log.Fatal("❌ Redis 监控服务发生严重错误: {Error}", ex.Message);
throw;
}
finally
{
_isRunning = false;
Log.Information("⏹️ Redis 监控服务已停止");
}
}
public void Stop()
{
Log.Information("🛑 正在停止 Redis 监控服务");
_cancellationTokenSource.Cancel();
}
private async Task EnsureRedisRunningAsync()
{
Log.Information("🔧 确保 Redis 正在运行");
try
{
if (!_processManager.IsRedisRunning())
{
Log.Information("⚠️ Redis 未运行,正在启动...");
var startResult = await _processManager.StartRedisAsync();
if (!startResult)
{
Log.Error("❌ 启动 Redis 失败,执行强制重启");
await ForceKillAndRestartRedisAsync();
}
else
{
Log.Information("✅ Redis 启动成功");
}
}
else
{
Log.Information("✅ Redis 已在运行");
}
}
catch (Exception ex)
{
Log.Error("❌ 确保 Redis 运行时发生错误: {Error}", ex.Message);
await ForceKillAndRestartRedisAsync();
}
}
///
/// 强制终止所有 Redis 进程并快速重启
///
private async Task ForceKillAndRestartRedisAsync()
{
try
{
Log.Warning("� 执行强制 Redis 进程终止和重启");
// 1. 立即强制终止所有 Redis 进程
await ForceKillAllRedisProcessesAsync();
// 2. 短暂等待系统清理
await Task.Delay(2000);
// 3. 快速重启
Log.Information("🚀 快速重启 Redis");
var startResult = await _processManager.StartRedisAsync();
if (!startResult)
{
Log.Error("❌ 快速重启失败,再次尝试");
await Task.Delay(1000);
await _processManager.StartRedisAsync();
}
else
{
Log.Information("✅ Redis 强制重启成功");
}
}
catch (Exception ex)
{
Log.Error("❌ 强制重启过程中发生错误: {Error}", ex.Message);
}
}
///
/// 强制终止所有 Redis 相关进程
///
private async Task ForceKillAllRedisProcessesAsync()
{
try
{
Log.Warning("� 强制终止所有 Redis 进程");
// 获取所有 Redis 相关进程
var redisProcessNames = new[] { "redis-server", "redis-cli", "redis-sentinel" };
foreach (var processName in redisProcessNames)
{
var processes = Process.GetProcessesByName(processName);
foreach (var process in processes)
{
try
{
if (!process.HasExited)
{
Log.Information("🔪 强制终止进程: {ProcessName} (PID: {ProcessId})", processName, process.Id);
process.Kill(entireProcessTree: true); // 终止整个进程树
// 等待进程完全终止
if (!process.WaitForExit(5000))
{
Log.Warning("⚠️ 进程 {ProcessId} 未在5秒内终止", process.Id);
}
else
{
Log.Information("✅ 进程 {ProcessId} 已终止", process.Id);
}
}
}
catch (Exception ex)
{
Log.Warning("⚠️ 终止进程 {ProcessId} 时发生错误: {Error}", process.Id, ex.Message);
}
finally
{
process.Dispose();
}
}
}
// 额外清理:使用系统命令强制终止
try
{
await ExecuteSystemCommandAsync("taskkill /f /im redis-server.exe");
await ExecuteSystemCommandAsync("taskkill /f /im redis-cli.exe");
}
catch (Exception ex)
{
Log.Debug("系统命令清理失败: {Error}", ex.Message);
}
Log.Information("✅ Redis 进程强制终止完成");
}
catch (Exception ex)
{
Log.Error("❌ 强制终止 Redis 进程时发生错误: {Error}", ex.Message);
}
}
///
/// 执行系统命令
///
private async Task ExecuteSystemCommandAsync(string command)
{
try
{
var processInfo = new ProcessStartInfo("cmd.exe", $"/c {command}")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
using var process = Process.Start(processInfo);
if (process != null)
{
await process.WaitForExitAsync();
}
}
catch (Exception ex)
{
Log.Debug("执行系统命令失败: {Command}, 错误: {Error}", command, ex.Message);
}
}
///
/// 简化的监控循环
///
private async Task SimplifiedMonitoringLoopAsync(CancellationToken cancellationToken)
{
Log.Information("🔄 启动简化监控循环 (检查间隔: {Interval}秒)", _settings.ProcessCheckIntervalSeconds);
while (!cancellationToken.IsCancellationRequested)
{
try
{
// 简单检查:Redis 是否运行
if (!_processManager.IsRedisRunning())
{
Log.Warning("⚠️ Redis 未运行,执行强制重启");
await ForceKillAndRestartRedisAsync();
}
else
{
// 简化的健康检查
await PerformSimplifiedHealthCheckAsync();
}
// 等待下次检查
await Task.Delay(_settings.ProcessCheckIntervalSeconds * 1000, cancellationToken);
}
catch (OperationCanceledException)
{
Log.Information("🛑 监控循环已取消");
break;
}
catch (Exception ex)
{
Log.Error("❌ 监控循环错误: {Error}", ex.Message);
// 发生任何错误都执行强制重启
await ForceKillAndRestartRedisAsync();
await Task.Delay(3000, cancellationToken);
}
}
Log.Information("⏹️ 监控循环已停止");
}
///
/// 简化的健康检查 - 检查连接、数据读写功能和性能
///
private async Task PerformSimplifiedHealthCheckAsync()
{
try
{
var timeSinceLastCheck = DateTime.Now - _lastHealthCheck;
if (timeSinceLastCheck.TotalSeconds < _settings.HealthCheckIntervalSeconds)
{
return; // 还没到检查时间
}
_lastHealthCheck = DateTime.Now;
// 执行增强的健康检查,包含超时机制
var healthCheckPassed = await PerformEnhancedHealthCheckWithTimeoutAsync();
if (!healthCheckPassed)
{
Log.Warning("⚠️ Redis 健康检查失败,执行强制重启");
await ForceKillAndRestartRedisAsync();
return;
}
Log.Information("✅ Redis 健康检查通过");
}
catch (Exception ex)
{
Log.Error("❌ 健康检查失败: {Error}", ex.Message);
// 健康检查失败就强制重启
await ForceKillAndRestartRedisAsync();
}
}
///
/// 执行增强的健康检查,包含连接测试、数据读写测试和超时机制
///
private async Task PerformEnhancedHealthCheckWithTimeoutAsync()
{
const int timeoutSeconds = 5;
var testKey = $"health_check_{DateTime.Now:yyyyMMddHHmmss}_{Guid.NewGuid():N}";
var testValue = $"test_value_{DateTime.Now.Ticks}";
try
{
Log.Debug("🔍 开始增强健康检查 - 测试键: {TestKey}", testKey);
// 使用CancellationToken实现5秒超时
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds));
try
{
// 1. 基本连接测试
var pingTask = TestRedisConnectionAsync();
var pingResult = await ExecuteWithTimeoutAsync(pingTask, cts.Token);
if (!pingResult)
{
Log.Warning("⚠️ Redis PING 测试失败");
return false;
}
Log.Debug("✅ Redis PING 测试通过");
// 2. 数据写入测试
var writeTask = TestRedisWriteAsync(testKey, testValue);
var writeResult = await ExecuteWithTimeoutAsync(writeTask, cts.Token);
if (!writeResult)
{
Log.Warning("⚠️ Redis 数据写入测试失败");
return false;
}
Log.Debug("✅ Redis 数据写入测试通过");
// 3. 数据读取测试
var readTask = TestRedisReadAsync(testKey, testValue);
var readResult = await ExecuteWithTimeoutAsync(readTask, cts.Token);
if (!readResult)
{
Log.Warning("⚠️ Redis 数据读取测试失败");
return false;
}
Log.Debug("✅ Redis 数据读取测试通过");
return true;
}
catch (OperationCanceledException) when (cts.Token.IsCancellationRequested)
{
Log.Warning("⚠️ Redis 健康检查超时 ({TimeoutSeconds}秒),操作响应过慢", timeoutSeconds);
return false;
}
}
catch (Exception ex)
{
Log.Error("❌ 增强健康检查过程中发生错误: {Error}", ex.Message);
return false;
}
finally
{
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
await CleanupTestDataAsync(testKey, cts.Token); // 需修改方法支持CancellationToken
// 清理测试数据
}
}
///
/// 执行带超时的任务 (.NET Core 3.1 兼容版本)
///
private async Task ExecuteWithTimeoutAsync(Task task, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource();
// 注册取消回调
using var registration = cancellationToken.Register(() =>
tcs.TrySetCanceled(cancellationToken));
// 等待原始任务完成
_ = task.ContinueWith(t =>
{
if (t.IsFaulted)
tcs.TrySetException(t.Exception.InnerException ?? t.Exception);
else if (t.IsCanceled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(t.Result);
}, TaskContinuationOptions.ExecuteSynchronously);
return await tcs.Task;
}
///
/// 测试 Redis 数据写入功能
///
private async Task TestRedisWriteAsync(string key, string value)
{
try
{
var command = $"SET {key} \"{value}\"";
var result = await _processManager.ExecuteRedisCliCommandAsync(command);
var success = !string.IsNullOrEmpty(result) && result.Contains("OK");
if (success)
{
Log.Debug("✅ Redis 写入操作成功: {Key} = {Value}", key, value);
}
else
{
Log.Warning("⚠️ Redis 写入操作失败: {Result}", result);
}
return success;
}
catch (Exception ex)
{
Log.Error("❌ Redis 写入测试异常: {Error}", ex.Message);
return false;
}
}
///
/// 测试 Redis 数据读取功能
///
private async Task TestRedisReadAsync(string key, string expectedValue)
{
try
{
var command = $"GET {key}";
var result = await _processManager.ExecuteRedisCliCommandAsync(command);
var success = !string.IsNullOrEmpty(result) && result.Trim().Trim('"') == expectedValue;
if (success)
{
Log.Debug("✅ Redis 读取操作成功: {Key} = {Value}", key, result);
}
else
{
Log.Warning("⚠️ Redis 读取操作失败: 期望值 '{ExpectedValue}', 实际值 '{ActualValue}'", expectedValue, result);
}
return success;
}
catch (Exception ex)
{
Log.Error("❌ Redis 读取测试异常: {Error}", ex.Message);
return false;
}
}
///
/// 清理测试数据
///
private async Task CleanupTestDataAsync(string testKey, CancellationToken token)
{
try
{
if (!string.IsNullOrEmpty(testKey))
{
var command = $"DEL {testKey}";
var result = await _processManager.ExecuteRedisCliCommandAsync(command, token);
Log.Debug("🧹 清理测试数据: {Key}, 结果: {Result}", testKey, result);
}
}
catch (Exception ex)
{
Log.Debug("⚠️ 清理测试数据时发生错误: {Error}", ex.Message);
// 清理失败不影响主流程,只记录日志
}
}
///
/// 测试 Redis 连接
///
private async Task TestRedisConnectionAsync()
{
try
{
// 使用 redis-cli 执行简单的 PING 命令
var result = await _processManager.ExecuteRedisCliCommandAsync("PING");
return !string.IsNullOrEmpty(result) && result.Contains("PONG");
}
catch (Exception ex)
{
Log.Debug("Redis 连接测试失败: {Error}", ex.Message);
return false;
}
}
public bool IsRunning => _isRunning;
public void Dispose()
{
_cancellationTokenSource?.Cancel();
_processManager?.Dispose();
_cancellationTokenSource?.Dispose();
}
}
}