部署
生产拓扑、横向扩展、外部指标与追踪、备份与升级,以及随附参考清单的状态。
在生产环境运行 Cordy Gateway 的受支持方式,是同时使用 docker-compose.prod.yml 与文档中的 docker-compose.production-overrides.yml。本页介绍生产拓扑、如何扩展、连接由运维管理的可观测性,以及第二天运维。首次起栈请从快速开始开始。
生产拓扑
docker-compose.prod.yml 在一台 Docker 主机上运行完整技术栈:
客户端 ──► nginx ──► gateway(1..N 副本)──► pgbouncer ──► postgres
(LB / TLS) │ ▲
└──────────► redis │
worker ┘
管理员 ──► admin(Django)─────────────────► postgres, redis
| 服务 | 角色 | 暴露 |
|---|---|---|
nginx | 负载均衡与 TLS 终止点;在网关副本间轮询 | 发布 GATEWAY_HTTP_PORT(默认 8002) |
gateway | 数据平面;可扩展到 N 副本 | 内部 8002,在 nginx 之后 |
admin | 控制平面(Django) | 发布 ADMIN_HTTP_PORT(默认 8001) |
pgbouncer | 网关热路径的事务池 | 仅内部 |
postgres | PostgreSQL 18 + pg_cron | 仅内部 |
redis | 速率限制、配额、缓存、冷却、幂等、缓冲 | 仅内部 |
worker | 后台用量结算与审计上传 | 仅内部 |
Postgres、PgBouncer 与 Redis 绝不对主机发布。nginx 默认终止明文 HTTP——请在 docker/nginx/ 加入 443 server block 与证书,或用你自己的反向代理或负载均衡器置于技术栈之前。
上游生产文件没有映射 ENVIRONMENT、CORS/代理控制、指标控制、多项运行时限制、Admin 门户 URL 或信用扣减 WAL。只有 Compose 文件引用的 .env 值才会进入容器。执行下方任一命令前,先创建必需的生产覆盖文件;只用基础生产文件会让 Gateway 采用 development 默认值。
起栈:
docker compose \
-f docker-compose.prod.yml \
-f docker-compose.production-overrides.yml \
--env-file .env up -d --build
横向扩展
网关服务没有固定的容器名,且位于 nginx 之后,因此你可以运行多个副本。用 Compose 扩容或缩容:
# 运行 4 个网关副本
docker compose \
-f docker-compose.prod.yml \
-f docker-compose.production-overrides.yml \
--env-file .env up -d --scale gateway=4
由于所有共享状态都存于 Redis 与 Postgres,增加副本是安全的:速率限制、配额、冷却与幂等都是集群级的。每个副本运行 GRANIAN_WORKERS 个 worker 进程(默认 8);按主机 CPU 调节每副本的 worker 数。
容量规划
吞吐量在很大程度上取决于你的上游供应商时延、硬件、模型与载荷大小——务必测量你自己的工作负载。以下是来自单台测试主机内部基准测试的粗略参考:
- 一个有用的规划量级是:轻量工作负载下每个网关副本约 ~500 请求/秒。
- 在一次内部基准测试中,架构在
scale=4下以零服务端错误持续承载 ~2,151 RPS,且随副本增加路由时延保持有界。
这些是在受限测试台上的基准观测,而非保证。请增加副本,并针对你真实的流量与供应商重新测量,同时关注下文的指标。
可观测性
生产可观测性使用由你运维、且能从生产网络到达的基础设施。Gateway 提供带认证的 Prometheus 格式指标,并可导出 OTLP/HTTP 追踪。
指标
Gateway 位于公开 nginx 之后时,在 .env 设置强令牌,并让 CIDR 绕过保持为空:
GATEWAY_METRICS_TOKEN=<metrics-token>
GATEWAY_METRICS_ALLOWED_CIDRS=
通过生产覆盖文件应用设置,再让现有的 Prometheus 兼容抓取器访问公开 HTTPS 端点:
docker compose \
-f docker-compose.prod.yml \
-f docker-compose.production-overrides.yml \
--env-file .env up -d gateway nginx
scrape_configs:
- job_name: cordy-gateway
scheme: https
metrics_path: /metrics/prometheus
authorization:
type: Bearer
credentials: <metrics-token>
static_configs:
- targets: [gateway.example.com]
CIDR 检查使用直接 socket 对端。端点位于公开 nginx 后方时,允许 nginx 或其网络会在令牌校验前放行它代理的所有公共请求。只有抓取器通过直接、隔离的受信路径连接时,才使用 GATEWAY_METRICS_ALLOWED_CIDRS。
有用的指标族包括 gateway_requests、gateway_requests_error、gateway_tokens、gateway_cost_usd、gateway_failover_success_rate、gateway_routing_overhead_ms 与 gateway_provider_circuit_breaker_state。
追踪(OpenTelemetry)
按配置在 .env 中设置完整 OTLP/HTTP trace URL 与请求头,再应用生产覆盖文件。collector 主机名必须能从 Gateway 容器解析;其 HTTPS 证书必须受容器信任;网络策略必须允许向其发送流量。
随附配置的定位
docker-compose.monitoring.yml、docker-compose.tracing.yml 与 docker-compose.observability.yml 都是开发/参考配置。监控服务加入外部开发网络,而生产 nginx 与 Gateway 加入 cordy-link-prod-network;tracing 与 observability collector 同样不与生产 Gateway 共享网络。observability 配置还带 CHANGEME 默认值。这些文件可作为源码示例,但不是生产叠加文件;除非另行设计并验证网络、密钥、存储与访问控制部署,否则不要把它们加入生产命令。
信用扣减 WAL
生产覆盖文件把具名卷 gateway_wal 挂载到 /var/lib/cordy,并把 Redis 失败备份写入 /var/lib/cordy/credit-consume.jsonl。这样容器重建后仍保留追加式证据。随附镜像以 root 运行并可写入挂载目录;若重新分发的镜像改用自定义 UID,必须在承载流量前创建目录并授予该 UID 写权限。
该 WAL 是软失败计费记录,不是带自动消费者的队列。Redis 拒绝信用扣减缓冲写入时,请求仍完成,成本则追加到文件;追加也失败时,Gateway 会计数一笔少扣款。仓库没有自动重放工具;请按运维说明人工保留与核对 WAL 记录。
备份与升级
第二天运维以包裹 compose 技术栈的 make 目标提供:
| 任务 | 命令 | 作用 |
|---|---|---|
| 备份 | make backup | 逻辑 pg_dump 到 BACKUP_DIR(脚本默认 ./backups;生产模板为 /var/backups/cordy;保留 BACKUP_RETENTION)。 |
| 灾备演练 | make dr-drill | 备份、还原到一个一次性数据库并验证——RTO/RPO 代理。 |
| 升级预检 | make preflight | 升级前的只读检查。 |
| 升级 | make upgrade | 预检 → 备份 → 迁移 → 验证。用 DRY_RUN=1 预览。 |
| 升级回滚 | make upgrade-rollback BACKUP=… | 从升级备份还原数据库。 |
| 健康自检 | make health-check | 客户侧检查 Postgres、Redis、网关与备份。 |
| 验收检查 | make acceptance-check | 运行部署验收清单并输出报告。 |
数据库迁移由 Admin 服务拥有,并在 Admin 启动时自动运行;升级会作为 make upgrade 的一部分应用新迁移。
Kubernetes:仅供参考
k8s/下的 Kubernetes 清单仅供参考且未经验证。它们未经端到端运行,不是受支持的部署路径。生产环境请使用docker-compose.prod.yml。
若你为集群改编这些清单,请将其视为起点并自行验证完整路径——数据库接线(DB_*,而不仅是 DATABASE_URL)、Ingress 请求体大小限制、密钥与迁移。kubectl --dry-run=client 只检查 YAML 语法;它不证明服务能启动或能处理流量。
运维清单
- 在 nginx(或外层代理)终止 TLS,并设置
DJANGO_SECURE_SSL_REDIRECT=True。 - 在 Admin 与 Gateway 上一致地设置
CHANNEL_ENCRYPTION_KEYS,并存放于密钥管理系统。 - 每次创建、重建或扩容都应用
docker-compose.production-overrides.yml。 - Gateway 位于公开 nginx 后方时,用 bearer 令牌保护
/metrics/prometheus;除非抓取路径直接且隔离,否则让 CIDR 绕过保持为空。 - 若浏览器会调用网关,显式设置
CLIENT_CORS_ORIGINS;生产环境绝不使用*。 - 上线前配置并测试备份;就绪后启用 WAL 归档/PITR 并设置
REQUIRE_PITR=1。 - 验证
/var/lib/cordy可写并保留gateway_wal卷;数据库 WAL/PITR 与信用扣减 JSONL WAL 解决不同的恢复问题。 - 把网关副本扩展到你实测的吞吐量,并关注故障转移与错误指标。