Skip to content

后台任务与多实例协调

除了处理 HTTP 请求,Sub2API 还运行多种周期任务和 worker。它们决定 token、订阅、统计、备份和异步任务能否长期保持健康。

主要后台任务

任务作用
Token Refresh提前刷新 OAuth token
Account Expiry到期账号自动暂停
Proxy Expiry到期代理切换或恢复
Subscription Expiry更新订阅状态和提醒
Payment Order Expiry对账、关闭超时订单
Usage Cleanup批量删除历史用量
Idempotency Cleanup清理过期幂等记录
Dashboard Aggregation生成仪表盘小时/日统计
Ops Metrics/Aggregation采集系统指标和预聚合
Ops Cleanup删除过期错误、指标和日志
Ops Alert Evaluator根据规则生成告警事件
Scheduled Reports生成周期运维报告
Scheduler Snapshot更新账号调度快照
Channel Monitor定时检测渠道模板与状态
Scheduled Account Test执行账号测试计划
Backup定时或手动数据库备份
Batch Image Worker消费图片任务、轮询和结算
Platform Quota Flusher批量回写用户平台配额

Leader Lock

多实例不能让每个副本都执行同一个全量任务。通用策略:

  1. 使用 Redis SET NX 获取带 owner 和 TTL 的 leader lock。
  2. 被其他实例持有时跳过本轮。
  3. Redis 出错时,部分任务回退 PostgreSQL advisory lock。
  4. 任务完成后 compare-and-delete 释放。
  5. 下一轮重新竞选,不永久绑定 leader。

TTL 必须大于任务最坏执行时间,否则锁执行中到期,另一个实例可能同时开始。

Heartbeat

Ops job heartbeat 用于区分:

  • 任务正常执行但本轮无数据。
  • 任务未被当前实例选为 leader。
  • 任务卡死或长时间没有运行。
  • 任务运行失败。

告警应根据计划周期设置阈值。例如每天一次的 cleanup 不能使用 5 分钟无心跳告警。

Token Refresh

周期刷新会扫描接近过期的 OAuth 账号,并且每个账号仍需要独立刷新锁。全局任务选主只能避免重复扫描,账号锁用于防止请求热路径与后台刷新并发。

监控:

  • refresh request/success/failure。
  • lock contention 和 wait time。
  • OAuth 401 cooldown。
  • refresh token rotation 后持久化失败。

过期任务

账号、代理、订阅和订单的“过期”含义不同:

  • 账号:可以自动设为不可调度。
  • 代理:可能切换 fallback proxy,并保留原 proxy ID 供恢复。
  • 订阅:更新状态并发送提醒。
  • 支付订单:先尝试 reconcile,再标记过期。

这些任务不应通过数据库定时器替代,因为它们还涉及缓存、通知和外部平台查询。

聚合与清理

直接在仪表盘扫描全部 usage_logs 会越来越慢。聚合任务生成小时、日表,清理任务按保留期删除原始或中间数据。

部署时要保证:

  • 聚合已经覆盖将要删除的原始数据。
  • cleanup 使用小批次,避免长事务和表膨胀。
  • PostgreSQL 有 autovacuum 和磁盘余量。
  • 任务失败有告警,不是静默跳过。

Batch Image Worker

批量图片任务包含 ready、delayed、active、inflight 和 lock 状态。Worker 需要处理:

  • 新任务消费。
  • 上游异步提交。
  • 延迟轮询。
  • worker 崩溃后的 stale active 恢复。
  • 余额冻结、结算和释放。
  • 输入输出保留与清理。

启用该功能后,Redis 队列和对象存储不再是可忽略的附属依赖。

Worker Pool 与应用退出

用量、邮件、批量任务等 worker 在应用退出时需要 Stop/StopAndWait。部署平台要提供足够 termination grace period,让:

  1. 停止接受新请求。
  2. 取消周期任务。
  3. 等待关键用量任务完成。
  4. 释放数据库和 Redis 连接。

直接 SIGKILL 会中断尚未落库的内存任务。

多实例配置要求

  • 所有副本使用相同 Redis 和 PostgreSQL。
  • 系统时间和时区一致。
  • leader lock key 不被不同环境共用。
  • staging 与 production 必须使用不同 Redis DB/前缀和数据库。
  • 每个实例有唯一 instance ID。
  • 总数据库连接池按实例数计算。

运维检查

每天或通过告警观察:

  • job heartbeat 是否更新。
  • leader lock 是否长期不释放。
  • scheduler outbox lag/backlog。
  • usage worker waiting/dropped/sync fallback。
  • quota flusher dirty/readd/error。
  • cleanup 删除数量与耗时。
  • batch queue ready/delayed/active 数量。
  • token refresh 失败账号数量。

本文档用于帮助你理解、部署和运维 Sub2API。使用前请确认上游服务条款与当地法律要求。