Files
gyxx-flow/docs/deployment.md
T
wangyunlong dc8be88e60 chore(config): 工作流配置、清单与文档同步
workflows/schedules/commands/notification-routing 与 source-manifests 四模块
清单同步登录统一化与新工作流(product.hk_anpei_public_inventory.daily 等);
docs 运维手册、控制台与耗时分布文档、CI 关键脚本清单、AGENTS 指南更新;
测试与模块注册对齐。
2026-10-09 13:45:30 +08:00

230 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GYXX Flow 部署
## 推荐部署方式
生产环境推荐使用 Linux 主机:
- PostgreSQL 使用云端服务,完整 DSN 由服务器密钥环境注入。
- Python 调度器、本机 Hermes 和需要登录状态的浏览器运行在宿主机。
- systemd 只守护一个 Python 调度进程,所有业务时间规则仍来自 `config/schedules.json`。
- 运行数据使用 `/var/lib/gyxx-flow`,不得把生产 `GYXX_DATA_ROOT` 指向源码目录中的 `var/`。
这种方式能够直接访问两个本机 Hermes 角色和浏览器 CDP,也不会把业务定时规则复制到 systemd timer、cron 或 Windows Task Scheduler。
## 环境要求
- Python 3.12 和 `uv`
- 可访问的 PostgreSQL 13+ 云端实例及运行时注入的 `GYXX_POSTGRES_DSN`
- 本机 Hermes `data-analyzer` 与 `data-collector`
- Chrome 与 Scrapling 浏览器运行时,以及个别业务入口仍需要的 PowerShell 运行条件
- 可访问现有飞书身份的专用系统用户
创建生产目录和服务账户:
```bash
sudo useradd --system --create-home --shell /usr/sbin/nologin gyxx-flow
sudo install -d -o gyxx-flow -g gyxx-flow /opt/gyxx-flow
sudo install -d -o gyxx-flow -g gyxx-flow /var/lib/gyxx-flow
sudo install -d -o root -g gyxx-flow -m 0750 /etc/gyxx-flow
```
将代码发布到 `/opt/gyxx-flow` 后安装锁定依赖:
```bash
cd /opt/gyxx-flow
sudo -u gyxx-flow uv sync --python 3.12 --no-group dev --frozen
sudo -u gyxx-flow uv run scrapling install
```
业务采集代码只使用 Scrapling;其动态与隐身抓取器所需的底层浏览器由
Scrapling 安装和管理。具体边界与验证命令见
[`architecture.md`](architecture.md#scrapling-采集边界)。
凭据放入 `/etc/gyxx-flow/gyxx-flow.env`,权限设为 `0640`。该文件不提交到 Git,至少按实际环境注入数据库密码、飞书身份和可选 Hermes 密钥。
控制台和调度器都支持可重复的 `--env-file`,只加载显式列出的文件。systemd 的
`EnvironmentFile=` 或当前进程环境优先于文件中的同名值,避免本地文件意外覆盖密钥系统
注入值。
## 香港安沛 SKU 公有库存同步
`product.hk_anpei_public_inventory.daily` 每天按 `Asia/Shanghai` 09:00 查询计划书中的固定 SKU 清单,
调用聚水潭 `/open/inventory/query`,并按商品编码(光影)更新飞书电子表格「現有庫存」工作表的
「仓库现有库存」列。它要求调度进程环境提供
`JUSHUITAN_APP_KEY` 和 `JUSHUITAN_APP_SECRET`;`JUSHUITAN_BASE_URL` 可选,默认使用聚水潭官方 OpenAPI
地址。没有密钥时工作流会在查询前失败,不会把库存留成 0 或改写多维表格。
Windows NSSM 调度服务从受保护的运行时环境文件读取凭据。安装器默认读取通用运行环境文件
`D:\product-collector-analyze-flow\.env`,以及独立的聚水潭密钥文件
`D:\product-collector-analyze-flow\private-secrets\jushuitan.env`。两个文件都按服务账户实际身份限制 ACL;
可分别通过 `-RuntimeEnvFile` 和 `-JushuitanEnvFile` 指定其他路径:
```powershell
.\deploy\windows-service\install.ps1 -ProjectRoot D:\gyxx-flow -DataRoot D:\gyxx-flow-data -RuntimeEnvFile D:\product-collector-analyze-flow\.env -JushuitanEnvFile D:\product-collector-analyze-flow\private-secrets\jushuitan.env
```
仅将这两个变量的正式聚水潭应用值写入服务账户可读的环境文件,并限制文件 ACL;不要使用开发配置中的默认值,
也不要把真实值写进 Git、PowerShell 命令参数、服务日志或文档。已安装的服务需要让调度进程重新读取环境文件后,
新计划才会使用这些值。Linux 部署则将相同变量放入权限为 `0640` 的 `EnvironmentFile`。
## 三平台电商费用日报部署边界
`product.ecommerce_costs.daily` 是包含天猫万相台、京东京准通和抖音千川分支的电商费用工作流;三个
平台下载节点并行,导入节点分别等待本平台下载完成。当前项目对其中天猫万相台这条
浏览器链路按 Windows Server + NSSM 验收;Linux 上的通用调度器说明不等于万相台浏览器流程
已经完成 Linux/无头浏览器验收。部署到 Windows Server 时使用项目内的 NSSM 服务包装器,业务
时间仍只由 `config/schedules.json` 管理,不创建 Windows Task Scheduler 条目。
该工作流需要由服务账户注入以下环境变量,真实值不要写入 Git、命令参数或文档:
```text
GYXX_DATA_ROOT=D:\gyxx-flow-data
GYXX_POSTGRES_DSN=<云端 PostgreSQL DSN>
WANXIANG_ACCOUNT=<万相台账号>
WANXIANG_PASSWORD=<yourpassword>
```
未显式设置 `WANXIANG_USER_DATA_DIR` 时,登录态保存在
`<GYXX_DATA_ROOT>\state\browser-profiles\wanxiang-ads`。这个 Profile 是该脚本的独立登录态,
不要与其他淘宝/万相台脚本共用。使用 NSSM 的 `AppEnvironmentExtra` 或服务器密码管理器注入
凭据;不要把真实密码写进 PowerShell 脚本或 `nssm` 命令历史。
安装 Windows 常驻服务:
```powershell
cd D:\gyxx-flow
uv sync --python 3.12 --group dev
.\deploy\windows-service\install.ps1 -ProjectRoot D:\gyxx-flow -DataRoot D:\gyxx-flow-data
# 按服务器密码管理器的方式为 gyxx-flow-scheduler 注入上述环境变量
nssm start gyxx-flow-scheduler
```
首次上线先在有头浏览器中建立登录态并导入一日数据;验证码或滑块必须在同一 Profile 中人工
完成:
```powershell
$env:GYXX_DATA_ROOT = 'D:\gyxx-flow-data'
$env:WANXIANG_ACCOUNT = '<从密码管理器读取>'
$env:WANXIANG_PASSWORD = '<yourpassword>'
uv run gyxx doctor --json
uv run gyxx scripts run product.tmall_wanxiang_ads.collect --date 2026-08-17 --execute
uv run gyxx scripts run product.import.tmall_ads --date 2026-08-17 --execute
```
确认手工链路成功后,再让唯一的 `gyxx schedule run` 常驻服务接管;不要为 19:30 另建系统定时
任务。完整的服务重启和 dry-run 流程见本文件的“systemd 调度服务”章节以及
[`runbook.md`](runbook.md) 的万相台小节。
## PostgreSQL
从受限环境文件加载云端数据库连接:
```bash
cd /opt/gyxx-flow
set -a
source /etc/gyxx-flow/gyxx-flow.env
set +a
uv run gyxx doctor --json
```
生产环境必须设置 `GYXX_POSTGRES_DSN`,且 DSN 主机必须是非回环地址。项目不会把云端地址、用户名或密码写入源码;`deploy/postgres.compose.yml` 仅保留为开发和恢复场景的可选本地工具,不是当前生产数据库入口。
## 本机 Hermes
启动并验证两个独立角色:
```text
data-analyzer: API base http://127.0.0.1:8642/v1
data-collector: API base http://127.0.0.1:8643/v1
```
`28790/28791` 不作为工作流业务端点。
运行时配置必须保持回环地址。Hermes 不可用时,纯采集、文件处理、数据库同步和不依赖大模型的确定性通知仍可运行;仍依赖 Hermes 的工作流应保持停用或手工执行,不得静默改用远程 AI。飞书消息投递本身统一依赖运行服务账户的 `hermes-analyzer` lark-cli user 授权。
例外:`content.summary.weekly` / `content.summary.monthly` 的内容报告、`product.style_analysis.interval` 的款式周期分析,以及 `product.video_upload` / `product.jd_video_upload` 的视频标题与视觉颜色识别,均配置为显式直连 MiniMax。内容报告使用 `CONTENT_ANALYSIS_LLM_BASE_URL`、`CONTENT_ANALYSIS_LLM_MODEL` 和 `CONTENT_ANALYSIS_LLM_API_KEY`;商品/视频链路使用 `STYLE_ANALYSIS_LLM_*`(视频链路也支持 `GYXX_DIRECT_LLM_*` 覆盖)。这些链路不读取 Hermes 分析端口,但仍保留本地结果校验、断点、EffectLedger、飞书和 PostgreSQL 写入链路。
## 上线前验证
使用生产服务账户运行:
```bash
cd /opt/gyxx-flow
sudo -u gyxx-flow env GYXX_DATA_ROOT=/var/lib/gyxx-flow uv run gyxx doctor --json
sudo -u gyxx-flow env GYXX_DATA_ROOT=/var/lib/gyxx-flow uv run gyxx schedule run --dry-run --once
sudo -u gyxx-flow env GYXX_DATA_ROOT=/var/lib/gyxx-flow uv run gyxx list --json
```
开发或发布流水线另外执行:
```bash
uv run ruff check src tests
uv run pytest
uv build
uv run gyxx acceptance status --json
```
## systemd 调度服务
项目提供 `deploy/gyxx-flow.service`。安装并启动:
```bash
sudo cp /opt/gyxx-flow/deploy/gyxx-flow.service /etc/systemd/system/gyxx-flow.service
sudo systemctl daemon-reload
sudo systemctl enable --now gyxx-flow.service
sudo systemctl status gyxx-flow.service
```
unit 的唯一业务入口是:
```text
/opt/gyxx-flow/.venv/bin/python -m gyxx_flow schedule run
```
若 unit 不使用 systemd `EnvironmentFile=`,入口必须显式追加:
```text
--env-file /etc/gyxx-flow/gyxx-flow.env
```
调度状态写入 `/var/lib/gyxx-flow/state/scheduler`,日志和子进程产物写入同一外置数据根。修改 `config/schedules.json` 后先运行一次 dry-run,再重启服务:
```bash
sudo -u gyxx-flow env GYXX_DATA_ROOT=/var/lib/gyxx-flow \
/opt/gyxx-flow/.venv/bin/python -m gyxx_flow schedule run --dry-run --once
sudo systemctl restart gyxx-flow.service
```
不要为单个工作流创建 systemd timer 或 cron 条目,也不得同时运行两个调度器实例。
## 发布更新
```bash
sudo systemctl stop gyxx-flow.service
cd /opt/gyxx-flow
# 切换到已验收版本后:
sudo -u gyxx-flow uv sync --python 3.12 --no-group dev --frozen
sudo -u gyxx-flow env GYXX_DATA_ROOT=/var/lib/gyxx-flow uv run gyxx doctor --json
sudo -u gyxx-flow env GYXX_DATA_ROOT=/var/lib/gyxx-flow uv run gyxx schedule run --dry-run --once
sudo systemctl start gyxx-flow.service
```
代码发布和回滚都不得覆盖 `/var/lib/gyxx-flow`。
## Docker 边界
当前 Compose 只负责 PostgreSQL。完整应用若进入容器,容器内 `127.0.0.1` 不再指向宿主机的两个 Hermes 和浏览器 CDP;同时部分工作流仍可能依赖可见桌面登录或 PowerShell。因此在完成网络、安全、浏览器 Profile 持久化和目标工作流验收前,不将完整生产应用声明为纯容器部署。
## Windows 兼容入口
`deploy/windows-service/` 暂时保留为 legacy NSSM 兼容入口。NSSM 只守护同一个 `gyxx schedule run` 进程,不注册 Windows Task Scheduler,也不保存业务时间规则。新服务器部署以 Linux systemd 为准。
## Windows 工作站保活(控制台 + 调度器自检自启动)
交互式 Windows 工作站(无法用 systemd/NSSM 常驻服务时)使用 `deploy/watchdog/gyxx_keepalive.py` 做进程外保活:
- **控制台自检**:控制台进程内置看门狗线程(`console.py` `_console_watchdog`),周期探测自身 `GET /api/health`;连续失败(默认 3 次,`GYXX_CONSOLE_WATCHDOG_FAILURES` / `GYXX_CONSOLE_WATCHDOG_INTERVAL_SECONDS` 可调,`GYXX_CONSOLE_WATCHDOG=0` 关闭)即以退出码 70 自杀,交给保活拉起。`/api/health` 不鉴权、只报进程 PID、uptime 与调度锁存活,供探针使用;API 500 现在会把完整堆栈落到 stderr(随启动重定向进 `var/logs/console-restarts/`)。
- **保活脚本**:登录自启动(Startup 目录 `gyxx-keepalive.vbs` → `pythonw gyxx_keepalive.py`)后常驻,每 30 秒一轮:控制台探测连续失败或端口空置则结束僵死进程树并按 `--env-file` 同款参数拉起;读 `var/state/scheduler/service.lock` 判定调度器存活,锁主死亡即拉起 `gyxx schedule run`(调度器单实例锁保证不双跑)。单目标冷却 120 秒;30 分钟内 5 次重启触发熔断,暂停拉起 1 小时并记日志待人工检查。日志在 `var/logs/keepalive/keepalive.log`。
- **验收**:`python deploy/watchdog/gyxx_keepalive.py --once` 单轮探测+处置;健康态应只输出 `keepalive-start`/`keepalive-once-done`。
- 该脚本只做进程可用性守护,不承载任何业务时间规则(唯一调度路径仍是 `gyxx schedule run`);未注册 Windows Task Scheduler。注意:Startup 方式要求用户已登录——机器重启后需人工登录一次,之后控制台与调度器会在约 2 分钟内自动就位。