XuJiacheng b2b3a6cf91 fix: 调整Kafka检查跳过时段和告警触发阈值
将Kafka检查跳过时段结束时间从4点延长至5点,并将数据库连接失败告警触发阈值从8次提高到10次,以减少误告警
2026-04-03 18:47:57 +08:00
2025-11-20 09:56:33 +08:00
2025-11-20 09:56:33 +08:00
2025-11-20 09:56:33 +08:00
2025-11-20 09:56:33 +08:00
2025-11-20 09:57:03 +08:00
2025-11-20 09:56:33 +08:00
2025-11-20 09:56:33 +08:00
2025-11-20 09:56:33 +08:00
2025-11-20 09:56:33 +08:00

Web_AutoNotificatPhone_Server_Prod

1. 项目概述

这是一个基于 ASP.NET Core 8 MVC 的通知与巡检服务,核心职责是:

  1. 提供 HTTP API接收“电话/短信”通知请求并发布到 Redis 频道。
  2. 运行后台定时任务(TimerClass),每分钟做系统状态检查。
  3. 根据 Redis 指标和 PostgreSQL 心跳数据触发自动告警(短信 + 电话)。

项目本质上是一个“告警编排层”:

  • 输入来源HTTP 请求、Redis 指标、PostgreSQL 心跳表。
  • 输出目标Redis 发布(供下游呼叫/短信系统消费)。

2. 技术栈与依赖

  • .NET: net8.0
  • Web: ASP.NET Core MVC + API Controller
  • Redis: CSRedisCore
  • PostgreSQL: Npgsql
  • Logging: NLog

AutoNotificatPhone.csproj 关键包:

  • CSRedisCore
  • NLog
  • Npgsql

3. 目录与核心文件

  • Program.cs应用启动、CORS、路由、HostedService 注册。
  • Controllers/CallAndMsgController.cs:通知入站 API电话/短信)。
  • Models/TimerClass.cs:后台巡检与告警主流程。
  • CSRedisCacheHelper.csRedis 连接与基础操作封装。
  • Models/SmsRequest.cs:通知请求模型。
  • Models/ReturnInfo.cs:统一接口返回结构。
  • appsettings.json日志级别、Postgres 连接配置。
  • nlog.config:日志落盘规则。

4. 启动流程(程序生命周期)

4.1 Program 启动阶段

Program.cs 主要行为:

  1. AddControllersWithViews():注册 MVC 和 API 支持。
  2. 注册 CORS 策略 AllowAnyOrigin
    • 允许任意源
    • 允许任意方法
    • 允许任意请求头
  3. AddHostedService<TimerClass>():注册后台巡检服务。
  4. 管道顺序:
    • UseStaticFiles()
    • UseRouting()
    • UseCors("AllowAnyOrigin")
    • UseAuthorization()
    • MapControllerRoute(...)

4.2 后台服务启动

应用启动后,TimerClass 自动运行:

  • 持续循环,直到应用停止。
  • 每分钟固定在第 30 秒执行一次巡检逻辑。

5. API 处理流程CallAndMsgController

5.1 路由

Controller 路由前缀:

  • api/CallAndMsg/{action}

核心接口:

  • POST api/CallAndMsg/SendToPhone

5.2 请求模型SmsRequest

  • PhoneNumber:目标手机号
  • CallerName:任务标识/来电显示名
  • Content:消息内容
  • StartingPoint开始时间Unix 秒)
  • DeadLine截止时间Unix 秒)
  • Type1 电话,2 短信

5.3 接口执行逻辑

SendToPhone 内部流程:

  1. 接收 SmsRequest
  2. 组装 notification 对象。
  3. 使用固定频道 MsgAndCall 发布到 Redis
    • CSRedisCacheHelper.Publish("MsgAndCall", payload)
  4. 返回 ReturnInfo
    • 成功:status=200 + 根据 Type 返回“已加入队列”文案
    • 失败:status=500 + 异常信息

说明:ConvertTimestampToIso 名称为“转 ISO”但实际仍返回 Unix 秒。


6. Redis 封装CSRedisCacheHelper

6.1 连接

静态初始化时连接本地 Redis

  • Host: 127.0.0.1
  • Port: 10079
  • 密码:代码中硬编码
  • DB0: redis
  • DB1: redis1

6.2 用途

  • DB0:主要用于发布通知频道(MsgAndCall)。
  • DB1主要用于读取巡检指标CPU、在线数、收发包等

6.3 方法

  • Set/Get/Forever/Del/Contains
  • Publish

7. 核心TimerClass 业务流程详解

TimerClass 是项目核心,分为 调度层检查层告警层

7.1 调度层(每分钟触发)

主循环执行顺序:

  1. 计算下次执行时间(每分钟第 30 秒)。
  2. 检查电话机进程是否在线(进程名 Telephone)。
  3. 运行整点任务调度。
  4. 依次执行检查任务:
    • CPU 阈值
    • RCU 在线数量
    • 总发送包
    • 总接收包
    • PostgreSQL 心跳

出现异常时:

  • 记录日志
  • 延迟 10 秒重试

7.2 整点任务调度

方法:RunHourlyNotificationTask()

规则:

  • 使用北京时间UTC+8
  • 非整点(Minute != 0)不执行。
  • 同一整点只执行一次(_executedTasks 去重)。
  • 10/15/22 点执行每日任务,其余整点发整点短信。

7.2.1 整点短信SendHourlySms

  • Mobile1 发送一条短信任务。
  • 文案包含当前“月/日/时”。

7.2.2 每日任务ExecuteDailyTask

  • Mobile1Mobile2 发送短信。
  • Mobile1 发送电话任务。
  • 任意发送失败记录错误日志。

7.3 Redis 指标检查

7.3.1 CPU 检查CheckCpuThreshold

步骤:

  1. 读取 UDPPackage_DetectTime
    • 若超过 10 分钟未更新,触发“监控程序无法访问”告警。
  2. 读取:
    • UDPPackage_CPUMax
    • UDPPackage_CPUAvg
    • UDPPackage_CPUMin
  3. CPUAvg 中满足“>=80 的点数达到 6 个”,触发 CPU 告警。

7.3.2 通用 Redis 规则CheckRedisValue

用于在线数/发送包/接收包的基线跌落判断:

  1. 读取 CSV 序列。
  2. 取前 baselineCount 个点做平均。
  3. 阈值 = 平均值 × thresholdRatio
  4. 若后续两个点都低于阈值,触发告警。

具体调用:

  • RCUOnLinebaselineCount=8ratio=0.8
  • UDPPackage_TotalSendPackagebaselineCount=8ratio=0.6
  • UDPPackage_TotalRecvPackagebaselineCount=8ratio=0.75

7.3.3 接收包特殊规则CheckTotalRecvPackage

在通用规则之前,先判断:

  • 若最后 3 个值都 < 70000,立即触发告警。

7.4 PostgreSQL 心跳检查

方法:CheckKafkaHeartbeatAsync()

目标判断“Kafka 入库是否活跃”。

流程:

  1. appsettings.jsonPostgres 节生成连接串。
  2. 查询 heartbeat.heartbeat_events
    • 先按 ts_ms desc 取最近 3000 条
    • 再按 write_ts_ms desc 取最新一条
  3. 结果为空或解析失败:走“数据库连接失败”告警路径。
  4. nowMs - lastTsMs > KafkaStaleMinutes:触发“入库停滞”告警。
  5. 异常(连接失败/SQL 异常)同样走“数据库连接失败”告警。

7.4.1 数据库连接失败节流

  • 字段:_kafkaDbConnectionAlertCount
  • 逻辑:失败累计到 KafkaDbAlertTriggerCount=8 才真正发一次告警,之后计数清零。

8. 告警发送机制

统一通过 SendAlert(...)

  1. 计算过期时间:
    • 普通:短信 1800 秒、电话 900 秒
    • 扩展:短信 3600 秒、电话 1800 秒
  2. 构造 3 条任务:
    • 短信:Mobile1
    • 短信:Mobile2
    • 电话:Mobile1
  3. 调用 CallAndMsgController.SendToPhone 投递。
  4. 任一失败,记录错误日志。

9. 配置说明

9.1 appsettings.json

当前包含:

  • Logging
  • AllowedHosts
  • Postgres
    • Host
    • Port
    • Database
    • User
    • Password
    • MaxConnections
    • IdleTimeoutMs

9.2 nlog.config

  • 文件落盘目录:{basedir}/Logs/{shortdate}
  • 文件:info_*.txterror_*.txt
  • 当前规则:
    • FATAL 写入 info 文件
    • Error 及以上写入 error 文件

10. 快速运行

10.1 开发运行

dotnet restore
dotnet build AutoNotificatPhone.csproj
dotnet run --project AutoNotificatPhone.csproj

默认开发地址见 Properties/launchSettings.json

  • http://localhost:5080

10.2 VS Code Tasks

项目已配置任务:

  • build
  • publish
  • watch

11. 对外接口示例

请求:

POST /api/CallAndMsg/SendToPhone
Content-Type: application/json

{
  "PhoneNumber": "13500000000",
  "CallerName": "测试任务",
  "Content": "测试短信内容",
  "StartingPoint": 1760000000,
  "DeadLine": 1760001800,
  "Type": "2"
}

成功响应:

{
  "isok": true,
  "message": "短信已加入发送队列",
  "status": 200,
  "response": "success"
}

12. 关键数据流(一句话版)

外部请求/定时巡检 -> 生成 SmsRequest -> CallAndMsgController -> Redis 频道 MsgAndCall -> 下游系统消费执行。


13. 当前实现中的注意点

  1. CallAndMsgControllerConvertTimestampToIso 命名与实现含义不一致(返回 Unix 秒)。
  2. CSRedisCacheHelper 中 Redis 密码硬编码在代码,不利于安全与环境切换。
  3. TimerClassKafkaStaleMinutes 与告警文案“3分钟内入库数据为0”存在语义不一致风险建议统一
  4. 当前 CORS 为完全放开,生产环境建议收敛来源。

14. 后续可优化方向(可选)

  1. 将手机号、阈值、执行小时、告警文案全部配置化。
  2. TimerClass 通过接口服务发送通知,避免直接 new Controller。
  3. 增加单元测试:
    • Redis 阈值计算
    • Kafka 心跳判定
    • 告警节流逻辑
  4. 增加健康检查端点(数据库/Redis 连通性)。

15. 维护建议

每次修改巡检规则后,至少验证:

  1. dotnet build 无编译错误。
  2. Redis 有模拟数据时告警触发正确。
  3. PostgreSQL 心跳超时/失败路径可复现。
  4. MsgAndCall 频道消息格式未破坏下游兼容。
Description
电话报警系统的接口和定时服务
Readme 971 KiB
Languages
C# 87.8%
HTML 8.9%
CSS 2.8%
JavaScript 0.5%