Files
Web_AutoNotificatPhone_Serv…/Models/TimerClass.cs
2025-11-20 09:56:33 +08:00

491 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using AutoNotificatPhone.Controllers;
using Common;
using System.Threading;
using NLog;
using System.Diagnostics;
namespace AutoNotificatPhone.Models
{
public class TimerClass : BackgroundService
{
// 日志记录器
public static Logger logger = LogManager.GetCurrentClassLogger();
// 通知接收手机号码
private static readonly string Mobile1 = "13509214696";
private static readonly string Mobile2 = "16620970520";
// 记录已执行任务的时间点
private Dictionary<DateTime, bool> _executedTasks = [];
// 消息控制器实例
private readonly CallAndMsgController _callAndMsgController = new();
/// <summary>
/// 后台服务主执行方法
/// </summary>
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
await Task.Factory.StartNew(async () =>
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
// 计算下次执行时间每分钟的30秒
var now = DateTime.UtcNow;
var nextRunTime = CalculateNextRunTime(now);
var delayTime = nextRunTime - now;
// 等待到下一个执行点
await Task.Delay(delayTime, cancellationToken);
// 检查电话机状态并记录日志
LogPhoneStatus(CheckPhoneIsOnline());
// 执行定时任务
await RegularlySendActiverecords();
// 执行系统检查任务
await CheckCpuThresholdAsync();
await CheckRcuOnlineAsync();
await CheckTotalSendPackageAsync();
await CheckTotalRecvPackageAsync();
}
catch (TaskCanceledException)
{
// 任务被取消时的处理
logger.Error("任务被取消");
break;
}
catch (Exception ex)
{
// 异常处理
logger.Error($"主循环发生错误: {ex.Message}");
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
}
}
}, TaskCreationOptions.LongRunning);
}
/// <summary>
/// 计算下次执行时间每分钟的30秒
/// </summary>
private DateTime CalculateNextRunTime(DateTime now)
{
var nextRunTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 30);
return now.Second >= 30 ? nextRunTime.AddMinutes(1) : nextRunTime;
}
/// <summary>
/// 记录电话机状态日志
/// </summary>
private void LogPhoneStatus(bool isOnline)
{
logger.Error(isOnline ? "电话机在线,开始判断!+++++str+++++" : "电话机不在线,下面内容可能不会执行!+++++err+++++");
}
/// <summary>
/// 检查电话机进程是否在线
/// </summary>
private bool CheckPhoneIsOnline()
{
try
{
// 通过进程名检查电话机是否运行
return Process.GetProcessesByName("Telephone").Length > 0;
}
catch (Exception ex)
{
logger.Error($"电话机进程检查失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 定时发送活动记录(整点任务)
/// </summary>
private async Task RegularlySendActiverecords()
{
// 转换为北京时间
var beijingTime = DateTime.UtcNow.AddHours(8);
//logger.Error($"每日任务检查 - 当前北京时间: {beijingTime:yyyy-MM-dd HH:mm:ss}");
// 检查是否整点
if (beijingTime.Minute != 0)
{
//logger.Error($"不满足整点任务触发条件 - 当前时间: {beijingTime:HH:mm}");
return;
}
// 创建整点时间键
var hourlyKey = new DateTime(beijingTime.Year, beijingTime.Month, beijingTime.Day, beijingTime.Hour, 0, 0);
// 检查任务是否已执行
if (_executedTasks.ContainsKey(hourlyKey))
{
//logger.Error($"跳过已执行的整点任务 - 时间点: {hourlyKey:yyyy-MM-dd HH:mm}");
return;
}
logger.Error($"准备执行整点短信任务 - 时间点: {hourlyKey:yyyy-MM-dd HH:mm}");
// 判断执行每日任务还是整点短信
if (beijingTime.Hour is 10 or 15 or 22)
{
await ExecuteDailyTask(beijingTime);
}
else
{
await SendHourlySms(beijingTime);
}
// 标记任务已执行
_executedTasks[hourlyKey] = true;
// 清理过期任务记录
CleanupOldTasks(beijingTime);
//logger.Error($"整点任务执行完成 - 时间点: {hourlyKey:yyyy-MM-dd HH:mm}");
}
/// <summary>
/// 清理过期任务记录
/// </summary>
private void CleanupOldTasks(DateTime currentTime)
{
// 找出所有过期的任务键
var keysToRemove = _executedTasks.Keys.Where(k => k.Date < currentTime.Date).ToList();
foreach (var key in keysToRemove)
{
_executedTasks.Remove(key);
//logger.Error($"清理过期任务记录: {key:yyyy-MM-dd HH:mm}");
}
}
/// <summary>
/// 发送整点短信
/// </summary>
private async Task SendHourlySms(DateTime beijingTime)
{
try
{
// 准备短信内容
long currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string dateTimeStr = $"{beijingTime.Month}月{beijingTime.Day}日{beijingTime.Hour}点";
string smsContent = $"[BLV运维提示] 整点系统状态报告。当前时间:{dateTimeStr}";
// 创建短信请求
var request = CreateSmsRequest(
type: "2",
deadline: currentTimestamp + 1800,
phone: Mobile1,
caller: "整点报告",
content: smsContent
);
// 发送短信并记录结果
var result = _callAndMsgController.SendToPhone(request);
/*logger.Error(result.isok
? $"整点短信已发送:{dateTimeStr}"
: $"发送整点短信失败:{result.message}");*/
}
catch (Exception ex)
{
logger.Error($"发送整点短信时出错:{ex.Message}");
}
await Task.CompletedTask;
}
/// <summary>
/// 执行每日定时任务10点、15点、22点
/// </summary>
private async Task ExecuteDailyTask(DateTime beijingTime)
{
try
{
// 准备消息内容
long currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string dateTimeStr = $"{beijingTime.Month}月{beijingTime.Day}日{beijingTime.Hour}点";
string smsContent = $"[BLV运维提示] 每日定时通知。当前时间为:{dateTimeStr}";
string callContent = $"BLV运维提示 每日定时通知 当前时间为 {dateTimeStr}";
// 创建短信和电话请求
var smsRequest1 = CreateSmsRequest("2", currentTimestamp + 1800, Mobile1, "每日定时通知", smsContent);
var smsRequest2 = CreateSmsRequest("2", currentTimestamp + 1800, Mobile2, "每日定时通知", smsContent);
var callRequest = CreateSmsRequest("1", currentTimestamp + 900, Mobile1, "每日定时通知", callContent);
// 发送通知
var smsResult1 = _callAndMsgController.SendToPhone(smsRequest1);
var smsResult2 = _callAndMsgController.SendToPhone(smsRequest2);
var callResult = _callAndMsgController.SendToPhone(callRequest);
// 记录发送结果
if (smsResult1.isok && smsResult2.isok && callResult.isok)
{
//logger.Error($"每日定时通知已发送:{dateTimeStr}");
}
else
{
logger.Error($"发送每日定时通知失败短信1={smsResult1.message} 短信2={smsResult2.message} 电话={callResult.message}");
}
}
catch (Exception ex)
{
logger.Error($"执行每日任务时出错:{ex.Message}");
}
await Task.CompletedTask;
}
/// <summary>
/// 检查CPU使用率阈值
/// </summary>
private async Task CheckCpuThresholdAsync()
{
try
{
// 检查监控程序是否在线
string detectTimeString = CSRedisCacheHelper.redis1.Get<string>("UDPPackage_DetectTime");
if (!string.IsNullOrEmpty(detectTimeString) &&
DateTime.TryParse(detectTimeString, out DateTime detectTime) &&
(DateTime.UtcNow - detectTime).TotalMinutes > 10)
{
// 监控程序无法访问警报
ExecuteMonitorUnavailableAlert(detectTime);
return;
}
// 获取CPU使用率数据
string cpuMax = CSRedisCacheHelper.redis1.Get<string>("UDPPackage_CPUMax");
string cpuAvg = CSRedisCacheHelper.redis1.Get<string>("UDPPackage_CPUAvg");
List<int> cpuMaxValues = ParseCpuValues(cpuMax);
List<int> cpuAvgValues = ParseCpuValues(cpuAvg);
// 记录CPU使用率
//logger.Error($"RCU服务器的CPU使用率-AVG:{cpuAvg},MAX:{cpuMax}");
// 检查是否超过阈值
if (CheckThreshold(cpuAvgValues, 70, 6))//(CheckThreshold(cpuMaxValues, 90, 6) || CheckThreshold(cpuAvgValues, 85, 6))
{
// 触发CPU警报
ExecuteCpuAlert(cpuMaxValues, ParseCpuValues(CSRedisCacheHelper.redis1.Get<string>("UDPPackage_CPUMin")), cpuAvgValues);
}
}
catch (Exception ex)
{
logger.Error($"CPU阈值检查错误: {ex.Message}");
}
await Task.CompletedTask;
}
/// <summary>
/// 检查RCU在线数量
/// </summary>
private async Task CheckRcuOnlineAsync()
{
await CheckRedisValueAsync("RCUOnLine", 8, 0.8, ExecuteRcuOnlineAlert, "RCU主机的在线数量");
}
/// <summary>
/// 检查总发送包数量
/// </summary>
private async Task CheckTotalSendPackageAsync()
{
await CheckRedisValueAsync("UDPPackage_TotalSendPackage", 8, 0.6, ExecuteTotalSendPackageAlert, "RCU主机的通讯数量");
}
/// <summary>
/// 检查总接收包数量
/// </summary>
private async Task CheckTotalRecvPackageAsync()
{
try
{
// 从Redis获取值
string valueString = CSRedisCacheHelper.redis1.Get<string>("UDPPackage_TotalRecvPackage");
if (string.IsNullOrEmpty(valueString)) return;
// 解析值
List<int> values = ParseCpuValues(valueString);
if (values == null || values.Count < 10) return;
// 检查最后3个值是否都小于70000
if (values.Count >= 3 && values[^3] < 70000 && values[^2] < 70000 && values[^1] < 70000)
{
// 触发警报
ExecuteTotalRecvPackageAlert([values[^3], values[^2], values[^1]]);
}
else
{
// 原有的阈值检查逻辑
await CheckRedisValueAsync("UDPPackage_TotalRecvPackage", 8, 0.75, ExecuteTotalRecvPackageAlert, "RCU主机的通讯数量");
}
}
catch (Exception ex)
{
logger.Error($"总接收包数量检查错误: {ex.Message}");
}
await Task.CompletedTask;
}
/// <summary>
/// 通用Redis值检查方法
/// </summary>
private async Task CheckRedisValueAsync(string redisKey, int baselineCount, double thresholdRatio, Action<List<int>> alertAction, string logPrefix)
{
try
{
// 从Redis获取值
string valueString = CSRedisCacheHelper.redis1.Get<string>(redisKey);
if (string.IsNullOrEmpty(valueString)) return;
// 解析值
List<int> values = ParseCpuValues(valueString);
if (values == null || values.Count < 10) return;
// 计算平均值和阈值
double average = values.Take(baselineCount).Average();
double threshold = average * thresholdRatio;
//logger.Error($"{logPrefix}-AVG:{average},ALL:{valueString}");
// 检查最后两个值是否低于阈值
if (values[baselineCount] < threshold && values[baselineCount + 1] < threshold)
{
// 触发警报
alertAction(values);
}
}
catch (Exception ex)
{
logger.Error($"{logPrefix}检查错误: {ex.Message}");
}
await Task.CompletedTask;
}
/// <summary>
/// 执行RCU在线数量警报
/// </summary>
private void ExecuteRcuOnlineAlert(List<int> values)
{
SendAlert(
smsContent: $"[BLV运维提示] RCU主机在线数量低于正常值请立即检查。数据{string.Join(",", values)}",
callContent: "BLV运维提示 RCU主机在线数量低于正常值 请立即检查",
alertType: "RCU-在线数量警报"
);
}
/// <summary>
/// 执行总发送包数量警报
/// </summary>
private void ExecuteTotalSendPackageAlert(List<int> values)
{
SendAlert(
smsContent: $"[BLV运维提示] RCU发送数量低于预期值请立即检查。数据{string.Join(",", values)}",
callContent: "BLV运维提示 RCU发送数量低于预期值 请立即检查",
alertType: "RCU-通讯数量警报"
);
}
/// <summary>
/// 执行总接收包数量警报
/// </summary>
private void ExecuteTotalRecvPackageAlert(List<int> values)
{
SendAlert(
smsContent: $"[BLV运维提示] RCU接收数量低于预期值请立即检查。数据{string.Join(",", values)}",
callContent: "BLV运维提示 RCU接收数量低于预期值 请立即检查",
alertType: "RCU-通讯数量警报"
);
}
/// <summary>
/// 执行CPU使用率警报
/// </summary>
private void ExecuteCpuAlert(List<int> cpuMax, List<int> cpuMin, List<int> cpuAvg)
{
string dataString = $"AVG:{string.Join(",", cpuAvg)},MAX:{string.Join(",", cpuMax)},MIN:{string.Join(",", cpuMin)}";
SendAlert(
smsContent: $"[BLV运维提示] RCU服务器的CPU使用率告警。{dataString}",
callContent: "BLV运维提示 RCU服务器的CPU使用率告警 请立即检查",
alertType: "RCU-CPU警报"
);
}
/// <summary>
/// 执行监控程序无法访问警报
/// </summary>
private void ExecuteMonitorUnavailableAlert(DateTime detectTime)
{
SendAlert(
smsContent: "[BLV运维提示] RCU服务器的监控程序无法访问请立即检查。",
callContent: "BLV运维提示 RCU服务器的监控程序无法访问 请立即检查",
alertType: "RCU-监控程序警报",
extendedDeadline: true
);
}
/// <summary>
/// 解析CPU值字符串为整数列表
/// </summary>
private List<int> ParseCpuValues(string valueString)
{
return string.IsNullOrEmpty(valueString)
? new List<int>()
: valueString.Split(',').Select(v => int.TryParse(v, out int result) ? result : 0).ToList();
}
/// <summary>
/// 检查值列表是否超过阈值
/// </summary>
private bool CheckThreshold(List<int> values, int threshold, int requiredCount)
{
return values != null &&
values.Count >= requiredCount &&
values.Count(v => v >= threshold) >= requiredCount;
}
/// <summary>
/// 通用警报发送方法
/// </summary>
private void SendAlert(string smsContent, string callContent, string alertType, bool extendedDeadline = false)
{
// 设置过期时间
long currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
long smsDeadline = extendedDeadline ? currentTimestamp + 3600 : currentTimestamp + 1800;
long callDeadline = extendedDeadline ? currentTimestamp + 1800 : currentTimestamp + 900;
// 创建请求
var smsRequest = CreateSmsRequest("2", smsDeadline, Mobile1, alertType, smsContent);
var smsRequest2 = CreateSmsRequest("2", smsDeadline, Mobile2, alertType, smsContent);
var callRequest = CreateSmsRequest("1", callDeadline, Mobile1, alertType, callContent);
// 发送警报
var smsResult = _callAndMsgController.SendToPhone(smsRequest);
var smsResult2 = _callAndMsgController.SendToPhone(smsRequest2);
var callResult = _callAndMsgController.SendToPhone(callRequest);
// 记录结果
if (smsResult.isok && callResult.isok)
{
//logger.Error($"{alertType}警告已发送");
}
else
{
logger.Error($"发送{alertType}通知失败: 短信={smsResult.message} 电话={callResult.message}");
}
}
/// <summary>
/// 创建短信/电话请求对象
/// </summary>
private SmsRequest CreateSmsRequest(string type, long deadline, string phone, string caller, string content)
{
return new SmsRequest
{
Type = type,
DeadLine = deadline,
StartingPoint = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
PhoneNumber = phone,
CallerName = caller,
Content = content
};
}
}
}