redis心跳添加

dev2.0
洁 任 2025-04-29 16:30:56 +08:00
parent a092d6cbe8
commit 91cb7a72db
2 changed files with 72 additions and 5 deletions

View File

@ -30,7 +30,7 @@ namespace Hopetry.Services
{ {
var key = $"{Prefix}{info.MachineId}"; var key = $"{Prefix}{info.MachineId}";
var json = JsonConvert.SerializeObject(info); var json = JsonConvert.SerializeObject(info);
await _db.StringSetAsync(key, json, TimeSpan.FromDays(30)); await _db.StringSetAsync(key, json, TimeSpan.FromMinutes(5));
} }
// 获取单个客户端信息 // 获取单个客户端信息
@ -65,6 +65,51 @@ namespace Hopetry.Services
return await _db.KeyDeleteAsync($"{Prefix}{machineId}"); return await _db.KeyDeleteAsync($"{Prefix}{machineId}");
} }
// 新增心跳键前缀
private const string HeartbeatPrefix = "heartbeat:";
// 更新客户端心跳(核心新增方法)
public async Task UpdateClientHeartbeatAsync(string machineId)
{
// 同时更新两个键的过期时间:
// 1. 客户端信息键(保持长期有效)
// 2. 心跳状态键(短期存活检测)
var tasks = new List<Task>
{
// 刷新客户端信息过期时间30天
_db.KeyExpireAsync($"{Prefix}{machineId}", TimeSpan.FromMinutes(5)),
// 设置/更新心跳状态带5分钟过期
_db.StringSetAsync(
$"{HeartbeatPrefix}{machineId}",
DateTime.UtcNow.ToString("o"),
expiry: TimeSpan.FromMinutes(5)
)
};
await Task.WhenAll(tasks);
}
// 获取所有活跃客户端ID基于心跳键
public async Task<List<string>> GetActiveClientIdsAsync()
{
var endpoints = _redis.GetEndPoints();
var server = _redis.GetServer(endpoints.First());
// 注意生产环境应改用SCAN
var heartbeatKeys = server.Keys(pattern: $"{HeartbeatPrefix}*");
return heartbeatKeys
.Select(k => k.ToString().Substring(HeartbeatPrefix.Length))
.ToList();
}
// 检查客户端是否活跃
public async Task<bool> IsClientActiveAsync(string machineId)
{
return await _db.KeyExistsAsync($"{HeartbeatPrefix}{machineId}");
}
public void Dispose() public void Dispose()
{ {
_redis?.Dispose(); _redis?.Dispose();

View File

@ -30,7 +30,6 @@ using Minio.Exceptions;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Security.AccessControl; using System.Security.AccessControl;
using Microsoft.VisualBasic; using Microsoft.VisualBasic;
using log4net.Util;
namespace HeBianGu.App.Disk namespace HeBianGu.App.Disk
{ {
@ -119,6 +118,7 @@ namespace HeBianGu.App.Disk
private IConfiguration config; private IConfiguration config;
private SemaphoreSlim _semaphore = new SemaphoreSlim(5); private SemaphoreSlim _semaphore = new SemaphoreSlim(5);
private Timer _progressTimer; private Timer _progressTimer;
private Timer _heartbeatTimer ;
private bool _isTimerRunning = false; private bool _isTimerRunning = false;
private object _timerLock = new object(); private object _timerLock = new object();
private bool _isUploading = false; // 新增:标记是否有上传任务正在运行 private bool _isUploading = false; // 新增:标记是否有上传任务正在运行
@ -129,6 +129,7 @@ namespace HeBianGu.App.Disk
private int regionCount = 0; private int regionCount = 0;
private ExplorerMinIOBehavior _explorerBehavior; private ExplorerMinIOBehavior _explorerBehavior;
private MinIOSearchBehavior _minioBehavior; private MinIOSearchBehavior _minioBehavior;
private Hopetry.Provider.SystemInfo systemInfo;
// 配置Redis连接 // 配置Redis连接
private RedisService redis = new RedisService("175.27.168.120:6050,password=HopetryRedis1406,connectRetry=3"); private RedisService redis = new RedisService("175.27.168.120:6050,password=HopetryRedis1406,connectRetry=3");
@ -150,11 +151,14 @@ namespace HeBianGu.App.Disk
DeleteFolderCommand = new AsyncRelayCommand(async () => await DeleteSelectedItemsAsync()); DeleteFolderCommand = new AsyncRelayCommand(async () => await DeleteSelectedItemsAsync());
DownloadCommand = new AsyncRelayCommand(async () => await DoDownloadCommand()); DownloadCommand = new AsyncRelayCommand(async () => await DoDownloadCommand());
SelectDirCommand = new CustomCommand(async () => await DoSelectDirCommand()); SelectDirCommand = new CustomCommand(async () => await DoSelectDirCommand());
systemInfo = SystemInfoCollector.Collect();
//SelectItemsCommand = new AsyncRelayCommand(async () => await RelayCommand<SystemInfoModel>(SelectItem)SelectItem()); //SelectItemsCommand = new AsyncRelayCommand(async () => await RelayCommand<SystemInfoModel>(SelectItem)SelectItem());
// 初始化Timer // 初始化Timer
_progressTimer = new Timer(1000); _progressTimer = new Timer(1000);
_progressTimer.Elapsed += UpdateProgress; _progressTimer.Elapsed += UpdateProgress;
_sendViewModel.UpLoadItems.CollectionChanged += (s, e) => { _sendViewModel.UpdateUploadingItems(); }; _heartbeatTimer = new Timer(30_000);
_heartbeatTimer.Elapsed += async (s, e) => await SendHeartbeatAsync();
_sendViewModel.UpLoadItems.CollectionChanged += (s, e) => { _sendViewModel.UpdateUploadingItems(); };
//加载上传完成列表 //加载上传完成列表
GetCompletedFiles(); GetCompletedFiles();
} }
@ -210,6 +214,22 @@ namespace HeBianGu.App.Disk
Application.Current.Dispatcher.Invoke(() => { _sendViewModel.Progress = progress; }); Application.Current.Dispatcher.Invoke(() => { _sendViewModel.Progress = progress; });
} }
//上传redis心跳检测
private async Task SendHeartbeatAsync()
{
try
{
// 上报心跳并更新客户端信息
//await redis.StoreClientInfoAsync(systemInfo);
await redis.UpdateClientHeartbeatAsync(systemInfo.MachineId);
}
catch (Exception ex)
{
// 处理网络异常等
Debug.WriteLine($"心跳上报失败: {ex.Message}");
}
}
private void StartProgressTimer() private void StartProgressTimer()
{ {
lock (_timerLock) lock (_timerLock)
@ -217,6 +237,7 @@ namespace HeBianGu.App.Disk
if (!_isTimerRunning) if (!_isTimerRunning)
{ {
_progressTimer.Start(); _progressTimer.Start();
_heartbeatTimer.Start();
_isTimerRunning = true; _isTimerRunning = true;
} }
} }
@ -229,6 +250,7 @@ namespace HeBianGu.App.Disk
if (_isTimerRunning) if (_isTimerRunning)
{ {
_progressTimer.Stop(); _progressTimer.Stop();
_heartbeatTimer.Stop();
_isTimerRunning = false; _isTimerRunning = false;
} }
} }
@ -401,7 +423,7 @@ namespace HeBianGu.App.Disk
_isUploading = true; _isUploading = true;
StartProgressTimer(); StartProgressTimer();
// 收集系统信息 // 收集系统信息
var systemInfo = SystemInfoCollector.Collect(); //var systemInfo = SystemInfoCollector.Collect();
try try
{ {
// 存储到Redis // 存储到Redis
@ -877,8 +899,8 @@ namespace HeBianGu.App.Disk
{ {
await DeleteMinIOItems(selectedItems); await DeleteMinIOItems(selectedItems);
_explorerBehavior.RefreshMinIOPath(CurrentMinIOPath);
MessageBox.Show($"已成功删除 {selectedItems.Count} 个项目"); MessageBox.Show($"已成功删除 {selectedItems.Count} 个项目");
_explorerBehavior.RefreshMinIOPath(CurrentMinIOPath);
SelectedItems.Clear(); SelectedItems.Clear();
} }
} }