# Genarrative 容器化压测与隔离部署方案 本目录只服务本机或预发的容器化模拟压测,不替换当前生产 `systemd + Nginx + Jenkins` 发布路径。生产服务器仍以 `deploy/systemd/`、`deploy/nginx/`、`scripts/jenkins-*.sh` 和 `scripts/deploy/production-api-deploy.sh` 为准。 ## 拓扑 ```text Docker Compose ├─ nginx :80 -> api-server:8082,负责静态站点、/admin/、/api/ 反代、upstream timing log、连接限制 ├─ api-server :8082,Linux release 构建,连接外部 SpacetimeDB ├─ otelcol :4317/4318,debug exporter,接收 traces / metrics / logs └─ k6 profile=loadtest 时临时启动,在 compose 网络内压 nginx ``` 默认 host 端口: - `http://127.0.0.1:18080`:容器 Nginx。 - `127.0.0.1:4317` / `127.0.0.1:4318`:容器 Collector OTLP gRPC / HTTP。 如端口冲突,可设置: ```powershell $env:GENARRATIVE_CONTAINER_HTTP_PORT="18081" $env:GENARRATIVE_CONTAINER_OTLP_HTTP_PORT="14318" $env:GENARRATIVE_CONTAINER_OTLP_GRPC_PORT="14317" ``` ## 初始化 ```bash npm run container:init ``` 该命令会从 `deploy/container/api-server.env.example` 生成本地 `deploy/container/api-server.env`。真实 token、库名和外部服务密钥只写本地 env 文件,不提交 Git。 Docker Desktop 下默认通过 `host.docker.internal:3101` 连接宿主机上 `npm run dev` 启动的 SpacetimeDB: ```env GENARRATIVE_SPACETIME_SERVER_URL=http://host.docker.internal:3101 GENARRATIVE_SPACETIME_DATABASE=genarrative-loadtest GENARRATIVE_SPACETIME_TOKEN= ``` Linux Docker Engine 如果不能解析 `host.docker.internal`,Compose 已配置 `host-gateway`;仍不通时把 `GENARRATIVE_SPACETIME_SERVER_URL` 改成宿主机网关 IP 或同网络内的 SpacetimeDB 地址。 ## 启动与验证 ```bash npm run container:config npm run container:build npm run container:up npm run container:ps curl -sS http://127.0.0.1:18080/api/runtime/puzzle/gallery ``` 查看日志: ```bash npm run container:logs -- nginx npm run container:logs -- api-server npm run container:logs -- otelcol ``` `npm run container:config` 默认只校验配置,不打印完整 env。排查 compose 展开结果时可临时使用: ```bash npm run container:config -- --print ``` 如果 `deploy/container/api-server.env` 已写入真实 token,不要把完整展开结果贴到公开渠道。 停止: ```bash npm run container:down ``` 如需同时清理容器卷: ```bash npm run container:down -- -v ``` ## 压测 k6 在 compose 网络内访问 `http://nginx`,避免 Windows 本机直连连接模型干扰 Linux 容器结果: ```bash npm run container:k6 ``` 作品列表脚本一次 iteration 默认请求两个公开列表接口,因此目标 500 HTTP req/s 对应 `PEAK_RPS=250`: ```powershell $env:SCENARIO="spike" $env:START_RPS="25" $env:PEAK_RPS="250" $env:HOLD="60s" $env:END_RPS="25" $env:PREALLOCATED_VUS="100" $env:MAX_VUS="500" $env:DETAIL_RATIO="0" npm run container:k6 ``` 如果要压 1000 HTTP req/s,把 `PEAK_RPS` 调到 `500`;如果要压 5000 HTTP req/s,把 `PEAK_RPS` 调到 `2500`,并同时提高 `PREALLOCATED_VUS` / `MAX_VUS`,观察是否先被带宽、Nginx `limit_conn` 或 api-server 背压限制。 ## OTLP 容器内 `otelcol` 默认使用 debug exporter。开启 api-server OTEL: ```env GENARRATIVE_OTEL_ENABLED=true OTEL_EXPORTER_OTLP_ENDPOINT=http://otelcol:4318 ``` 然后重建或重启容器: ```bash npm run container:up npm run container:logs -- otelcol ``` Collector 日志会输出 traces / metrics / logs。接 Rider、Jaeger、Tempo、Prometheus、Grafana 或托管平台时,另建独立 Collector 配置,不直接改生产 systemd 或 Nginx 模板。 ## 隔离边界 - 不改生产 systemd 单元。 - 不改 Jenkins 发布主流程。 - 不要求真实 HTTPS 证书。 - 不把真实 `.env`、`.env.local`、`.env.secrets.local` 或 `deploy/container/api-server.env` 放入 Docker build context。 - 不在容器镜像里内置 SpacetimeDB 数据或 token。