# 自动投放双服务部署 ## 1. Jenkins 构建 构建统一完整镜像,不再构建 `tencent-realtime-control` 独立镜像: ```bash set -e REGISTRY="registry.cn-hangzhou.aliyuncs.com/stuuudy" IMAGE="${REGISTRY}/ad-put-agent" cd "${WORKSPACE}" docker build \ -f Dockerfile.auto_put_ad_mini \ -t "${IMAGE}:latest" \ -t "${IMAGE}:${BUILD_TIMESTAMP}" \ . docker push "${IMAGE}:latest" docker push "${IMAGE}:${BUILD_TIMESTAMP}" ssh -i /root/.ssh/piaoquan.pem root@8.222.142.37 \ "sh /home/sh/deploy.sh ${BUILD_TIMESTAMP}" ``` ## 2. ECS 文件 将仓库中的 `docker-compose.yml` 放到 `/home/server/docker-compose.yml`。 当前部署兼容 ECS 已安装的 Docker Compose `2.27.0`。 两个服务共用现有的 `/home/server/.env`: ```bash chmod 600 /home/server/.env docker compose version ``` 原有数据库、ODPS、腾讯、飞书、OSS 和 AI 环境变量全部保留。 首次部署增加: ```dotenv RTC_START_HOUR=12 RTC_STOP_HOUR=21 RTC_POLL_SECONDS=600 RTC_HIGH_CPM=250 RTC_LOW_CPM=190 RTC_BID_UP_RATIO=1.05 RTC_MAX_PARTITION_LAG_HOURS=2 RTC_APPLY_ENABLED=0 RTC_COMMAND_ENABLED=1 RTC_COMMAND_CHAT_ID=oc_xxx RTC_COMMAND_ALLOWED_OPEN_IDS=ou_xxx RTC_COMMAND_CONFIRM_TTL_MINUTES=10 RTC_COMMAND_NEXT_DELIVERY_HOUR=6 RTC_COMMAND_DRAFT_TTL_MINUTES=5 RTC_NL_COMMAND_ENABLED=0 RTC_COMMAND_LLM_MODEL=google/gemini-3-flash-preview RTC_COMMAND_LLM_TIMEOUT_SECONDS=20 RTC_COMMAND_LLM_CONFIDENCE_THRESHOLD=0.85 OPEN_ROUTER_API_KEY=sk-or-v1-xxx DAILY_CREATION_ENABLED=0 DAILY_CREATION_HOUR=10 DAILY_CREATION_MINUTE=30 DAILY_REVIEW_ENABLED=0 DAILY_REVIEW_INTERVAL_HOURS=2 DAILY_RUN_ON_STARTUP=0 DAILY_REVIEW_RUN_ON_STARTUP=0 DAILY_SYNC_DELIVERY_TEMPLATE=0 DAILY_ROI_ENABLED=0 DAILY_ROI_HOUR=11 DAILY_ROI_MINUTE=0 DAILY_ROI_RUN_ON_STARTUP=0 ROI_APPLY_ENABLED=0 ROI_SHEET_APPROVAL_ENABLED=0 ROI_SHEET_APPROVAL_POLL_SECONDS=60 ROI_APPROVAL_TTL_MINUTES=120 ROI_SCALE_RATIO=1.10 ROI_SCALE_COOLDOWN_DAYS=3 ROI_MAX_BASE_RATIO=2.00 ROI_FISSION_PARAMETER_VERSION=20260712_A0-A15_v2 ROI_FEISHU_CHAT_ID=oc_xxx ``` 多个操作人使用英文逗号分隔 `RTC_COMMAND_ALLOWED_OPEN_IDS`。 代码默认 `RTC_APPLY_ENABLED=0`,日级创建、审核扫描、ROI 和模板同步也默认关闭; 缺少显式生产配置时不会创建广告或修改腾讯。 ## 3. ECS 部署脚本 `/home/sh/deploy.sh` 使用: ```bash #!/bin/bash set -e echo "Qingqu@2019" | docker login \ --username=stuuudys \ registry.cn-hangzhou.aliyuncs.com \ --password-stdin VERSION=${1:-latest} cd /home/server VERSION=${VERSION} docker compose --env-file /dev/null pull VERSION=${VERSION} docker compose --env-file /dev/null down --remove-orphans VERSION=${VERSION} docker compose --env-file /dev/null up -d VERSION=${VERSION} docker compose --env-file /dev/null ps ``` 继续沿用部署脚本中的 `source /home/server/.env`,Compose 同时通过标准 `env_file` 将同一个文件传给两个容器,环境变量文件和加载入口不变。 ## 4. 首次 dry-run 保持 `RTC_APPLY_ENABLED=0` 和两个 `DAILY_*_ENABLED=0`: ```bash cd /home/server docker compose --env-file /dev/null config --services docker compose --env-file /dev/null up -d docker compose --env-file /dev/null ps docker compose --env-file /dev/null logs --tail=200 ad_control_service docker compose --env-file /dev/null logs --tail=200 ad_daily_service ``` 控制服务启动时自动执行实时状态表增量迁移。也可以显式验证: ```bash docker compose --env-file /dev/null run --rm \ ad_control_service \ python /app/examples/tencent_realtime_control/init_db.py ``` 执行无腾讯写入的 CPM dry-run: ```bash docker compose --env-file /dev/null run --rm \ ad_control_service \ python /app/examples/tencent_realtime_control/run_once.py \ --at 2026-07-25T12:00:00 \ --cpm-override 220 \ --force-refresh ``` 飞书验证: 1. 在配置群 @机器人发送 `查看暂停状态`。 2. 发送 `查询今天自动化账户消耗`,确认返回腾讯实时汇总且不要求审批。 3. 发送一个单账户暂停命令,确认机器人返回预览和 `cmd_xxx`。 4. 回复确认,服务必须提示 dry-run 禁止写腾讯。 ## 5. 生产切换 1. 确认旧 `auto_put_ad_mini/server.py` 和旧实时容器不再运行。 2. 设置 `RTC_APPLY_ENABLED=1`,保持日级创建和 ROI 服务关闭。 3. 重新 `docker compose up -d`,观察一个完整实时周期。 4. 用单账户命令验证暂停、恢复、腾讯回读和飞书结果。 5. 设置 `DAILY_REVIEW_ENABLED=1`、`DAILY_SYNC_DELIVERY_TEMPLATE=1`。 6. 审核扫描稳定后设置 `DAILY_CREATION_ENABLED=1`。 7. 保持 `DAILY_RUN_ON_STARTUP=0`,防止部署时额外触发完整创建。 日级 ROI 单独分两阶段启用: 当前 `north_star_roi_t15_v5` 使用版本化传播裂变参数,报表版本为 `roi_report_v9`。小程序按人群包和转化目标、 公众号按合作方和公众号匹配传播裂变系数;企微优先按合作方精确匹配,合作方未匹配或样本不足时使用默认参考系数 2.5,不做渠道聚合回退。企微仅保留展示,不进入阈值和调控。首层效率收入读取 `效率收入`,T0 实际裂变收入读取当天的 `裂变效率收入`, 并以 T0 实际裂变收入乘传播裂变系数预测完整裂变收入。日级任务不会现场重算 cohort 参数。部署前应保持 `ROI_FISSION_PARAMETER_VERSION=20260712_A0-A15_v2`。参数必须先发布到 MySQL, 启动日志、数据库发布版本和 Excel 摘要中的参数版本、cohort 日期必须一致。 默认企微参考值使用独立版本 `qiwei_reference_2p5_v1`,并进入 ROI 批次幂等键, 避免与其他临时系数结果复用同一个运行批次。 ROI 在线表只上传一次,并发送到 `ROI_FEISHU_CHAT_ID` 和 `FEISHU_OPERATOR_CHAT_ID`;两个变量相同时只发送一次。 ROI 表格使用获得链接者可编辑权限。黄色【审批选择】列只接受“批准”或“拒绝”, 数据库隐藏幂等键决定真实执行目标,表格中的账户、广告、创意、成本和 ROI 不作为写入参数。 审批表默认展示三日窗口的日均首层 UV、日均首层效率收入、日均 LTV 预测效率收入和 日均成本;预测 ROI 仍按三日预测收入总和除以三日成本总和计算。三日汇总和每日明细 保留为隐藏审计列,不参与日均展示。 小程序和公众号 Sheet 展示所有进入阈值样本池的实体,企微 Sheet 展示全部参考实体; 各 Sheet 默认按预测 ROI 升序排列,动作列不参与排序。 1. 首次部署先执行下方参数发布命令并完成回读校验。 2. 设置 `DAILY_ROI_ENABLED=1`、`ROI_APPLY_ENABLED=0`、`ROI_SHEET_APPROVAL_ENABLED=0`,观察 11:00 的 ODPS 计算、数据库快照和可编辑飞书表。 3. 核对阈值、账户可执行范围、黄色审批列和动作数量。 4. 再设置 `ROI_APPLY_ENABLED=1`、`ROI_SHEET_APPROVAL_ENABLED=1`,重建 `ad-control-service`;批准一条低风险测试行,核对腾讯回读、表格结果和群通知。 5. 生产审批有效期默认 120 分钟;过期行不能执行。表格逐行选择“拒绝”不会产生腾讯写操作。 6. 不允许 `DAILY_ROI_ENABLED=0`、`ROI_APPLY_ENABLED=1`,也不允许仅开启表格审批而关闭 ROI 写操作;服务启动阶段会拒绝不完整配置。 首次启用前可手工运行一个“不发飞书、不写腾讯”的计算批次。该命令会读取 ODPS、 初始化/写入 ROI 数据库快照并在挂载目录生成本地 Excel: ```bash docker compose run --rm ad_daily_service \ python /app/examples/auto_put_ad_mini/run_daily_roi.py \ --end-date 20260725 ``` 确认数据库快照和本地报告后,再增加 `--send-feishu` 验证在线表、黄色审批列和链接编辑权限。 此时必须保持 `ROI_APPLY_ENABLED=0`、`ROI_SHEET_APPROVAL_ENABLED=0`,不会轮询或执行表格选择。 如果同一日期窗口的上游历史数据被修订,必须提供稳定的数据修订标识生成新批次,不能覆盖或删除已发布快照: ```bash docker compose run --rm ad_daily_service \ python /app/examples/auto_put_ad_mini/run_daily_roi.py \ --end-date 20260729 \ --source-revision datafix_20260730_1 \ --send-feishu ``` 相同 `--source-revision` 重复执行会复用同一批次;新的修订必须使用新的标识。日常调度不传此参数。 离线复算新参数必须与日级任务分开执行。以下命令默认只生成 SQL,不访问 ODPS: ```bash docker compose run --rm ad_daily_service \ python /app/examples/auto_put_ad_mini/refresh_roi_fission_multiplier.py \ --cohort-date 20260712 \ --sql-only ``` 去掉 `--sql-only` 才会固定执行小程序、公众号和企微三条只读 cohort SQL,并生成草稿 CSV/Excel。草稿不会自动 进入生产;必须审计并在 `roi_control/fission_multiplier.py` 登记版本和文件 SHA256。 小程序和公众号写入联合发布草稿,企微另行生成独立草稿。企微正式版本只需 登记企微 CSV 的 SHA256,数据库参数行只允许合作方精确匹配;不存在企微文件或参数行的旧版本继续使用默认参考系数 2.5。 首次上线或切换版本前,显式发布到 MySQL: ```bash docker compose run --rm ad_daily_service \ python /app/examples/auto_put_ad_mini/refresh_roi_fission_multiplier.py \ --publish-version 20260712_A0-A15_v2 \ --published-by production-deploy ``` 脚本会初始化参数表、写入不可变版本并立即回读校验。相同版本相同内容重复执行会 安全跳过;相同版本内容不同会拒绝覆盖。发布成功后再设置 `ROI_FISSION_PARAMETER_VERSION` 并启用日级 ROI。 ## 6. 验收与回滚 验收: ```bash docker compose --env-file /dev/null ps docker compose --env-file /dev/null logs --since=30m ad_control_service docker compose --env-file /dev/null logs --since=30m ad_daily_service ``` 应确认: - 两个容器均为 healthy。 - 实时循环每 10 分钟运行且没有双实例锁冲突。 - 飞书只有一个 WebSocket 消费者。 - 10:30 只出现一次创建任务。 - 审核扫描每 2 小时最多一个实例。 - 11:00 只生成一个相同指标/策略版本的 ROI 批次,同日重跑不会重复发布。 - ROI 审批执行与实时 CPM 调控不并发写腾讯,基础出价调整后两边状态一致。 回滚时将 `VERSION` 改为上一个镜像版本并重新部署。数据库新增表和列可以保留, 旧代码不会读取这些字段,不需要执行破坏性回滚。