feat: 实现 IoT 卡轮询系统(支持千万级卡规模)
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m35s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m35s
实现功能: - 实名状态检查轮询(可配置间隔) - 卡流量检查轮询(支持跨月流量追踪) - 套餐检查与超额自动停机 - 分布式并发控制(Redis 信号量) - 手动触发轮询(单卡/批量/条件筛选) - 数据清理配置与执行 - 告警规则与历史记录 - 实时监控统计(队列/性能/并发) 性能优化: - Redis 缓存卡信息,减少 DB 查询 - Pipeline 批量写入 Redis - 异步流量记录写入 - 渐进式初始化(10万卡/批) 压测工具(scripts/benchmark/): - Mock Gateway 模拟上游服务 - 测试卡生成器 - 配置初始化脚本 - 实时监控脚本 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 月流量追踪字段
|
||||
|
||||
系统 SHALL 在 IoT 卡模型中增加月流量追踪字段,用于处理跨月流量计算。
|
||||
|
||||
#### Scenario: 新增字段定义
|
||||
|
||||
- **WHEN** 系统需要追踪卡的月度流量使用情况
|
||||
- **THEN** 系统在 tb_iot_card 表增加以下字段:
|
||||
- `current_month_usage_mb` (DECIMAL): 本月已用流量(MB),默认值 0
|
||||
- `current_month_start_date` (DATE): 本月开始日期(自然月1日),默认值 NULL
|
||||
- `last_month_total_mb` (DECIMAL): 上月结束时的总流量(MB),默认值 0
|
||||
|
||||
#### Scenario: 字段用于跨月计算
|
||||
|
||||
- **WHEN** Gateway 返回月总流量(自然月累计)
|
||||
- **THEN** 系统使用这 3 个字段计算本月增量流量,处理跨月重置逻辑
|
||||
|
||||
#### Scenario: 兼容已有数据
|
||||
|
||||
- **WHEN** 数据库迁移执行,已有卡记录
|
||||
- **THEN** 系统为已有卡初始化 current_month_usage_mb=0、current_month_start_date=NULL、last_month_total_mb=0
|
||||
|
||||
### Requirement: 首次流量查询初始化
|
||||
|
||||
系统 SHALL 在卡首次查询流量时初始化月流量追踪字段。
|
||||
|
||||
#### Scenario: 首次查询初始化
|
||||
|
||||
- **WHEN** 卡A首次查询流量,current_month_start_date 为 NULL,Gateway 返回 total_usage_mb=500
|
||||
- **THEN** 系统初始化 current_month_start_date=当前月1日(如 2024-01-01),current_month_usage_mb=500,last_month_total_mb=0
|
||||
|
||||
#### Scenario: 非首次查询不重新初始化
|
||||
|
||||
- **WHEN** 卡A再次查询流量,current_month_start_date 不为 NULL
|
||||
- **THEN** 系统使用已有的 current_month_start_date,不重新初始化
|
||||
|
||||
### Requirement: 同月内流量增长
|
||||
|
||||
系统 SHALL 在同月内正确计算流量增量。
|
||||
|
||||
#### Scenario: 同月内流量增长
|
||||
|
||||
- **WHEN** 卡A上次查询在本月(current_month_start_date=2024-01-01),Gateway 返回 total_usage_mb=500,数据库当前 current_month_usage_mb=400
|
||||
- **THEN** 系统计算增量 100 MB,更新 current_month_usage_mb=500
|
||||
|
||||
#### Scenario: Gateway 返回值未变化
|
||||
|
||||
- **WHEN** Gateway 返回 total_usage_mb=400,等于数据库当前值 current_month_usage_mb=400
|
||||
- **THEN** 系统判断无增量,不触发套餐检查
|
||||
|
||||
#### Scenario: Gateway 返回值回退(异常)
|
||||
|
||||
- **WHEN** Gateway 返回 total_usage_mb=300,小于数据库当前值 current_month_usage_mb=400
|
||||
- **THEN** 系统记录警告日志,但仍更新为 Gateway 值(信任 Gateway 数据源)
|
||||
|
||||
### Requirement: 跨月流量重置
|
||||
|
||||
系统 SHALL 在检测到跨月时正确重置月流量统计。
|
||||
|
||||
#### Scenario: 跨月检测
|
||||
|
||||
- **WHEN** 卡A上次查询在上月(current_month_start_date=2024-01-01),当前时间为 2024-02-05
|
||||
- **THEN** 系统检测到跨月(当前月1日 > current_month_start_date)
|
||||
|
||||
#### Scenario: 跨月重置流程
|
||||
|
||||
- **WHEN** 检测到跨月,当前 current_month_usage_mb=400,Gateway 返回 total_usage_mb=50
|
||||
- **THEN** 系统执行:
|
||||
1. 保存 last_month_total_mb=400(上月结束值)
|
||||
2. 更新 current_month_start_date=2024-02-01(新月1日)
|
||||
3. 更新 current_month_usage_mb=50(新月流量)
|
||||
|
||||
#### Scenario: 跨多月(异常长时间未检查)
|
||||
|
||||
- **WHEN** 卡A上次查询在 2024-01-01,当前时间为 2024-04-05,跨越 3 个月
|
||||
- **THEN** 系统检测到跨月,重置到当前月(2024-04-01),记录警告日志(长时间未检查)
|
||||
|
||||
### Requirement: 月流量历史记录
|
||||
|
||||
系统 SHALL 在跨月时记录上月流量汇总到历史表。
|
||||
|
||||
#### Scenario: 记录上月汇总
|
||||
|
||||
- **WHEN** 检测到跨月,上月总流量为 400 MB
|
||||
- **THEN** 系统插入一条月度汇总记录到 data_usage_records 表(card_id、usage_mb=400、usage_type='monthly_summary'、recorded_at=上月最后一天)
|
||||
|
||||
#### Scenario: 历史记录供报表使用
|
||||
|
||||
- **WHEN** 管理员查询卡的月度流量报表
|
||||
- **THEN** 系统从 data_usage_records 表读取 usage_type='monthly_summary' 的记录
|
||||
|
||||
### Requirement: API 响应包含月流量字段
|
||||
|
||||
系统 SHALL 在卡详情和列表接口中返回月流量追踪字段。
|
||||
|
||||
#### Scenario: 卡详情接口返回
|
||||
|
||||
- **WHEN** 管理员请求查询卡详情
|
||||
- **THEN** 系统返回卡信息,包含 current_month_usage_mb、current_month_start_date、last_month_total_mb 字段
|
||||
|
||||
#### Scenario: 卡列表接口返回
|
||||
|
||||
- **WHEN** 管理员请求查询卡列表
|
||||
- **THEN** 系统返回卡列表,每张卡包含月流量追踪字段
|
||||
|
||||
#### Scenario: 历史兼容
|
||||
|
||||
- **WHEN** 客户端请求卡信息,旧版客户端不识别新字段
|
||||
- **THEN** 旧版客户端忽略新字段,不影响正常使用(向后兼容)
|
||||
|
||||
### Requirement: 数据库迁移
|
||||
|
||||
系统 SHALL 提供数据库迁移脚本增加月流量追踪字段。
|
||||
|
||||
#### Scenario: 迁移脚本添加字段
|
||||
|
||||
- **WHEN** 执行数据库迁移
|
||||
- **THEN** 系统执行 DDL:
|
||||
```sql
|
||||
ALTER TABLE tb_iot_card
|
||||
ADD COLUMN current_month_usage_mb DECIMAL(10,2) DEFAULT 0 COMMENT '本月已用流量(MB)',
|
||||
ADD COLUMN current_month_start_date DATE DEFAULT NULL COMMENT '本月开始日期',
|
||||
ADD COLUMN last_month_total_mb DECIMAL(10,2) DEFAULT 0 COMMENT '上月结束时总流量(MB)';
|
||||
```
|
||||
|
||||
#### Scenario: 迁移回滚
|
||||
|
||||
- **WHEN** 迁移失败需要回滚
|
||||
- **THEN** 系统执行回滚 DDL:
|
||||
```sql
|
||||
ALTER TABLE tb_iot_card
|
||||
DROP COLUMN current_month_usage_mb,
|
||||
DROP COLUMN current_month_start_date,
|
||||
DROP COLUMN last_month_total_mb;
|
||||
```
|
||||
|
||||
#### Scenario: 迁移不影响已有数据
|
||||
|
||||
- **WHEN** 迁移执行,表中有 1000 万条记录
|
||||
- **THEN** 系统添加字段使用默认值,不需要全表更新,迁移时间短(<5分钟)
|
||||
|
||||
### Requirement: Redis 缓存同步
|
||||
|
||||
系统 SHALL 在 Redis 缓存中同步月流量追踪字段。
|
||||
|
||||
#### Scenario: 缓存包含月流量字段
|
||||
|
||||
- **WHEN** 系统加载卡信息到 Redis 缓存(polling:card:{card_id})
|
||||
- **THEN** 缓存包含 current_month_usage_mb、current_month_start_date、last_month_total_mb 字段
|
||||
|
||||
#### Scenario: 更新缓存月流量字段
|
||||
|
||||
- **WHEN** 流量检查任务更新数据库后
|
||||
- **THEN** 系统使用 HSET 同步更新 Redis 缓存的月流量字段
|
||||
|
||||
#### Scenario: 缓存过期重新加载
|
||||
|
||||
- **WHEN** Redis 缓存过期,重新从数据库加载
|
||||
- **THEN** 系统加载完整的卡信息,包含最新的月流量字段
|
||||
|
||||
### Requirement: 数据一致性
|
||||
|
||||
系统 SHALL 确保月流量追踪字段在数据库和缓存之间的一致性。
|
||||
|
||||
#### Scenario: 更新事务保证一致性
|
||||
|
||||
- **WHEN** 流量检查任务更新月流量字段
|
||||
- **THEN** 系统在数据库事务中更新,提交成功后再更新 Redis 缓存
|
||||
|
||||
#### Scenario: 缓存更新失败不影响数据库
|
||||
|
||||
- **WHEN** 数据库更新成功,但 Redis 更新失败
|
||||
- **THEN** 系统记录警告日志,数据库数据为准,下次缓存加载时恢复一致
|
||||
|
||||
#### Scenario: 数据库更新失败回滚
|
||||
|
||||
- **WHEN** 更新月流量字段时数据库失败
|
||||
- **THEN** 系统事务回滚,不更新 Redis 缓存,保持原有数据
|
||||
|
||||
### Requirement: 监控和日志
|
||||
|
||||
系统 SHALL 记录月流量追踪相关的关键操作日志。
|
||||
|
||||
#### Scenario: 记录首次初始化日志
|
||||
|
||||
- **WHEN** 卡首次查询流量,初始化月流量字段
|
||||
- **THEN** 系统记录 Info 日志,包含 card_id、initialized_month、initial_usage_mb
|
||||
|
||||
#### Scenario: 记录跨月重置日志
|
||||
|
||||
- **WHEN** 检测到跨月并重置月流量统计
|
||||
- **THEN** 系统记录 Info 日志,包含 card_id、old_month、new_month、last_month_total_mb
|
||||
|
||||
#### Scenario: 记录异常日志
|
||||
|
||||
- **WHEN** 检测到流量回退或跨多月未检查
|
||||
- **THEN** 系统记录 Warn 日志,包含详细上下文
|
||||
Reference in New Issue
Block a user