Files

358 lines
8.9 KiB
Markdown
Raw Permalink 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.
# 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.cs`Redis 连接与基础操作封装。
- `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 秒)
- `Type``1` 电话,`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
-`Mobile1``Mobile2` 发送短信。
-`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. 若后续两个点都低于阈值,触发告警。
具体调用:
- `RCUOnLine``baselineCount=8``ratio=0.8`
- `UDPPackage_TotalSendPackage``baselineCount=8``ratio=0.6`
- `UDPPackage_TotalRecvPackage``baselineCount=8``ratio=0.75`
### 7.3.3 接收包特殊规则CheckTotalRecvPackage
在通用规则之前,先判断:
- 若最后 3 个值都 `< 70000`,立即触发告警。
## 7.4 PostgreSQL 心跳检查
方法:`CheckKafkaHeartbeatAsync()`
目标判断“Kafka 入库是否活跃”。
流程:
1.`appsettings.json``Postgres` 节生成连接串。
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_*.txt``error_*.txt`
- 当前规则:
- `FATAL` 写入 info 文件
- `Error` 及以上写入 error 文件
---
## 10. 快速运行
## 10.1 开发运行
```bash
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. 对外接口示例
请求:
```json
POST /api/CallAndMsg/SendToPhone
Content-Type: application/json
{
"PhoneNumber": "13500000000",
"CallerName": "测试任务",
"Content": "测试短信内容",
"StartingPoint": 1760000000,
"DeadLine": 1760001800,
"Type": "2"
}
```
成功响应:
```json
{
"isok": true,
"message": "短信已加入发送队列",
"status": 200,
"response": "success"
}
```
---
## 12. 关键数据流(一句话版)
外部请求/定时巡检 -> 生成 `SmsRequest` -> `CallAndMsgController` -> Redis 频道 `MsgAndCall` -> 下游系统消费执行。
---
## 13. 当前实现中的注意点
1. `CallAndMsgController``ConvertTimestampToIso` 命名与实现含义不一致(返回 Unix 秒)。
2. `CSRedisCacheHelper` 中 Redis 密码硬编码在代码,不利于安全与环境切换。
3. `TimerClass``KafkaStaleMinutes` 与告警文案“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` 频道消息格式未破坏下游兼容。