Skip to content

多实例与高可用部署

应用层可以运行多个副本,但高可用还要求 PostgreSQL、Redis、反向代理和上游账号池不存在单点。

参考拓扑

text
                   ┌──────────────┐
Internet ─────────▶│ Load Balancer│
                   └──────┬───────┘
                  ┌───────┴────────┐
                  ▼                ▼
            Sub2API A        Sub2API B
                  │                │
                  └───────┬────────┘
                      ┌───┴────┐
                      ▼        ▼
                 PostgreSQL   Redis

共享配置

所有副本必须一致:

  • JWT_SECRET
  • TOTP_ENCRYPTION_KEY
  • 数据库和 Redis endpoint。
  • 时区。
  • URL allowlist 和安全策略。
  • OAuth client secrets。
  • 计费、定价和 Gateway 关键配置。
  • 自定义 Codex instructions 模板。

推荐从同一个 Secret/Config source 注入,而不是手工编辑每台服务器。

实例本地状态

  • L1 cache。
  • HTTP/WS connection pool。
  • 内存 worker queue。
  • 本地日志。
  • 静态覆盖和本地数据文件。

滚动发布会中断该副本上的流式请求和 WebSocket。负载均衡器应先摘除实例,再等待连接排空。

负载均衡

普通 HTTP/SSE 请求可以 round-robin。WebSocket 和 previous response 场景可能受益于会话亲和,但不能只依赖 LB sticky:

  • Redis 会保存账号和会话提示。
  • 已建立 WS 连接仍只存在某个实例。
  • 实例退出后客户端必须重连。

如果开启 LB cookie sticky,确保它不影响 API 客户端或泄漏跨用户状态。

优雅发布

建议流程:

  1. LB 将实例标记为 draining。
  2. 停止新连接。
  3. 等待活跃 SSE/WS 到达可接受阈值。
  4. 发送 SIGTERM。
  5. 允许应用停止 worker 和关闭资源。
  6. 启动新版本并通过 /health
  7. 加回 LB,再处理下一个实例。

长连接可能持续数十分钟,需要设置最大 drain 时间,并接受少量客户端重连。

数据库连接

例如 4 个副本,每个 max_open_conns=100,理论上应用可打开 400 个连接。数据库还需要为迁移、备份和管理员预留。

扩应用副本时同步检查:

  • PostgreSQL max connections 和内存。
  • Redis pool 总连接数。
  • 上游账号总并发。
  • 反向代理 upstream keepalive。

后台任务

周期任务通过 Redis leader lock 或 PostgreSQL advisory lock 避免重复执行。检查:

  • 所有副本使用相同 lock backend。
  • 实例 ID 唯一。
  • Redis key 不与其他环境冲突。
  • lock TTL 大于任务最坏耗时。
  • job heartbeat 能看到 leader 和执行状态。

调度一致性

账号/分组变更通过缓存失效、outbox 和快照重建传播。多实例时关注:

  • scheduler outbox lag。
  • 某个实例是否长期使用旧快照。
  • Redis pub/sub 或版本 key 是否正常。
  • DB fallback 是否集中发生。

可以在不同实例分别发送带调试标识的请求,对比候选与配置版本。

PostgreSQL 高可用

应用只知道配置的数据库 endpoint。HA 方案应提供:

  • 稳定写 endpoint。
  • 自动主从切换。
  • 可接受的 DNS/连接恢复时间。
  • 备份与 PITR。

切主时旧连接会失败,应用连接池需要重新建立。把连接 lifetime 设置为有限值有助于长期回收旧连接。

Redis 高可用

Redis 选主切换期间,并发槽位、锁和缓存操作可能失败。HA 设计要验证:

  • 切换后应用是否自动连接新主。
  • Lua 脚本和 key 是否完整复制。
  • leader lock 不会同时被两个主接受。
  • AOF/RDB 丢失窗口是否可接受。

健康检查

/health 适合 LB 判断进程存活,但完整 readiness 还应通过外部探针验证:

  • PostgreSQL 查询。
  • Redis ping/脚本。
  • 测试分组的最小模型请求。
  • 用量记录是否落库。

不要让高频 LB health check 每次都调用付费上游;上游 smoke test 可以低频独立执行。

容量扩展顺序

  1. 确认瓶颈是应用 CPU/连接,而不是上游账号。
  2. 优化慢查询、日志和 worker。
  3. 扩 PostgreSQL/Redis 容量。
  4. 增加应用副本。
  5. 增加账号池与代理冗余。
  6. 重新计算所有连接池与告警阈值。

单纯增加应用副本不会增加上游账号额度。

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