Files
huang 804145332b
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 44s
chore: 归档轮询系统实现变更 (polling-system-implementation)
已完成千万级卡规模轮询系统的完整实现和集成测试验证,将变更归档到 openspec/changes/archive/2026-02-10-polling-system-implementation/

主要成果:
- 三大轮询任务:实名检查、卡流量检查、套餐流量检查
- 快速启动(<10秒)和渐进式初始化
- 完整运营工具:配置管理、并发控制、监控面板、告警系统、数据清理、手动触发
- 任务完成度:215/216(99.5%)
- 所有 24 个新增接口已生成 OpenAPI 文档

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 10:28:47 +08:00

8.0 KiB
Raw Blame History

ADDED Requirements

Requirement: 并发配置初始化

系统 SHALL 在启动时从数据库加载并发配置到 Redis。

Scenario: 首次启动加载配置

  • WHEN Worker 进程启动Redis 中没有并发配置
  • THEN 系统从 tb_polling_concurrency_config 表读取所有配置,写入 Redispolling:concurrency:config:{type}

Scenario: 配置已存在则跳过

  • WHEN Worker 进程启动Redis 中已有并发配置
  • THEN 系统跳过初始化,使用 Redis 中的配置(避免覆盖运行时修改)

Scenario: 数据库无配置则使用默认值

  • WHEN 数据库中没有并发配置记录
  • THEN 系统使用默认值(实名检查:50、流量检查:50、套餐检查:30、停复机:10写入 Redis

Requirement: 并发信号量获取

系统 SHALL 在任务执行前获取 Redis 信号量,控制并发数。

Scenario: 获取信号量成功

  • WHEN 实名检查任务开始,当前并发数为 30最大并发数为 50
  • THEN 系统执行 INCR polling:concurrency:current:realname返回值 31小于等于 50获取成功

Scenario: 并发已满拒绝执行

  • WHEN 实名检查任务开始,当前并发数为 50最大并发数为 50
  • THEN 系统执行 INCR 返回值 51大于 50立即 DECR 归还,任务返回 SkipRetry

Scenario: 信号量获取失败重试

  • WHEN 任务在并发已满时被拒绝
  • THEN 系统不重试直接返回等待下次调度周期10秒后再次尝试

Scenario: Redis 连接失败

  • WHEN INCR 操作因 Redis 连接失败
  • THEN 系统记录错误日志,任务失败,不执行业务逻辑

Requirement: 并发信号量释放

系统 SHALL 在任务完成后释放 Redis 信号量。

Scenario: 任务成功完成释放

  • WHEN 实名检查任务成功完成
  • THEN 系统执行 DECR polling:concurrency:current:realname释放信号量

Scenario: 任务失败也释放

  • WHEN 实名检查任务因 Gateway 超时失败
  • THEN 系统在 defer 中执行 DECR确保信号量释放

Scenario: Panic 恢复后释放

  • WHEN 任务执行中发生 panic
  • THEN 系统在 recover 后执行 DECR防止信号量泄漏

Scenario: DECR 失败记录日志

  • WHEN DECR 操作失败
  • THEN 系统记录错误日志,包含 task_type、task_id便于排查信号量计数异常

Requirement: 动态调整并发数

系统 SHALL 支持通过管理接口实时调整最大并发数,无需重启 Worker。

Scenario: 管理员提高并发数

  • WHEN 管理员调用接口,将实名检查最大并发数从 50 提高到 80
  • THEN 系统更新 RedisSET polling:concurrency:config:realname 80更新数据库配置表

Scenario: 管理员降低并发数

  • WHEN 管理员调用接口,将流量检查最大并发数从 50 降低到 30
  • THEN 系统更新 Redis 和数据库,当前正在执行的任务继续,新任务受新限制

Scenario: 调整后立即生效

  • WHEN 并发数调整完成
  • THEN 系统下次任务获取信号量时,使用新的最大并发数判断

Scenario: 并发数无效值校验

  • WHEN 管理员尝试设置并发数为 0 或负数
  • THEN 系统返回错误,提示并发数必须大于 0

Scenario: 并发数过大警告

  • WHEN 管理员尝试设置并发数大于 200
  • THEN 系统返回警告,提示过高并发可能打爆 Gateway建议值范围 10-100

Requirement: 查询并发状态

系统 SHALL 提供接口查询各类型任务的并发配置和实时并发数。

Scenario: 查询所有类型并发状态

  • WHEN 管理员请求查询并发状态
  • THEN 系统返回所有类型realname、carddata、package、stoprestart的最大并发数和当前并发数

Scenario: 查询单个类型并发状态

  • WHEN 管理员请求查询实名检查并发状态
  • THEN 系统返回 max_concurrency=50、current_concurrency=30、usage_rate=60%

Scenario: 并发数异常检测

  • WHEN 查询并发状态,发现当前并发数大于最大并发数
  • THEN 系统返回警告标志,提示可能存在信号量泄漏

Scenario: 长时间满载告警

  • WHEN 查询并发状态,某类型并发数连续 5 分钟保持满载usage_rate=100%
  • THEN 系统返回建议,提示可能需要提高并发数或优化任务性能

Requirement: 分类型并发控制

系统 SHALL 为不同任务类型(实名检查、流量检查、套餐检查、停复机)独立控制并发数。

Scenario: 实名检查独立控制

  • WHEN 实名检查任务获取信号量
  • THEN 系统使用 polling:concurrency:config:realname 和 polling:concurrency:current:realname

Scenario: 流量检查独立控制

  • WHEN 流量检查任务获取信号量
  • THEN 系统使用 polling:concurrency:config:carddata 和 polling:concurrency:current:carddata

Scenario: 套餐检查独立控制

  • WHEN 套餐检查任务获取信号量
  • THEN 系统使用 polling:concurrency:config:package 和 polling:concurrency:current:package

Scenario: 停复机独立控制

  • WHEN 停复机任务获取信号量
  • THEN 系统使用 polling:concurrency:config:stoprestart 和 polling:concurrency:current:stoprestart

Scenario: 互不影响

  • WHEN 实名检查并发满载50/50流量检查并发正常30/50
  • THEN 流量检查任务仍然可以正常获取信号量并执行,不受实名检查影响

Requirement: 并发配置持久化

系统 SHALL 将并发配置变更持久化到数据库。

Scenario: 更新配置同步数据库

  • WHEN 管理员调整并发数
  • THEN 系统先更新 Redis再更新数据库UPDATE tb_polling_concurrency_config SET max_concurrency=? WHERE task_type=?

Scenario: 数据库更新失败回滚

  • WHEN Redis 更新成功,但数据库更新失败
  • THEN 系统回滚 Redis 配置到原值,返回错误

Scenario: 启动时以数据库为准

  • WHEN Worker 进程重启Redis 和数据库配置不一致
  • THEN 系统以数据库配置为准,覆盖 Redis

Requirement: 并发监控统计

系统 SHALL 记录并发使用情况的监控统计。

Scenario: 记录峰值并发数

  • WHEN 每次任务获取信号量成功
  • THEN 系统更新 Redis Hashpolling:stats:concurrency:{type}),记录当前并发数,如果大于历史峰值则更新峰值

Scenario: 记录并发拒绝次数

  • WHEN 任务因并发已满被拒绝
  • THEN 系统增加 Redis Hash 的 reject_count_1h 计数

Scenario: 每小时重置统计

  • WHEN 每小时整点
  • THEN 系统重置 reject_count_1h保留 peak_concurrency持续统计

Requirement: 信号量计数修复

系统 SHALL 提供接口修复异常的信号量计数。

Scenario: 手动重置计数器

  • WHEN 管理员发现并发计数异常(如泄漏导致一直为 50 无法下降)
  • THEN 管理员调用接口,系统将 polling:concurrency:current:{type} 重置为 0

Scenario: 自动检测修复

  • WHEN 系统定期检查(每 5 分钟),发现当前并发数长时间不变且无任务执行
  • THEN 系统记录警告日志,建议管理员检查并手动修复

Scenario: 修复操作记录日志

  • WHEN 执行信号量重置
  • THEN 系统记录操作日志,包含操作人、重置前值、重置后值、原因

Requirement: 日志记录

系统 SHALL 记录并发控制的关键操作日志。

Scenario: 记录并发满载日志

  • WHEN 任务因并发已满被拒绝
  • THEN 系统记录 Info 日志,包含 task_type、current_concurrency、max_concurrency

Scenario: 记录配置变更日志

  • WHEN 管理员调整并发数
  • THEN 系统记录 Info 日志,包含 task_type、old_value、new_value、operator

Scenario: 记录信号量异常日志

  • WHEN DECR 失败或检测到计数异常
  • THEN 系统记录 Error 日志,包含详细上下文