Files
sanguo_moziplus_v2/docs/design/deployment-v2.6.md
T
2026-05-16 23:34:26 +08:00

13 KiB
Raw Blame History

v2.6 部署方案设计

版本: v2.6.2-deploy 基于: technical-design-v2.6.md v2.6.2 作者: 庞统(副军师)🐦 日期: 2026-05-16


1. 部署环境

项目 规格
主机 楚锋的 Mac mini (Apple M4, ARM64, 16GB RAM, macOS)
Python 3.11moziplus venv
Node.js v22.22.1
PM2 6.0.14
OpenClaw Gateway 127.0.0.1:18789
NAS 192.168.2.154SMB /Volumes/stock/
Windows-Test-Node 192.168.2.33

目录规划

用途 路径 说明
开发目录 ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/ Git 管理
安装目录 ~/.sanguo_projects/sanguo_moziplus_v2/ PM2 运行
Git 远程 gitee (origin) + gitea (NAS 192.168.2.154) 双远程

2. 部署架构

PM2 (进程管理器)
├── sanguo-moziplus-v2 (port 8083)     ← 🆕 v2 主进程(API + Daemon ticker + 前端)
├── sanguo-moziplus (port 8082)        ← v1 保留(v2 验证后下线)
├── sanguo-git-sync                    ← 不变
├── sanguo-mail-* (8个)                ← v2 验证后逐步下线
└── sanguo-mozi                        ← 不变

进程内部结构:
sanguo-moziplus-v2
├── uvicorn (FastAPI) — asyncio event loop
│   ├── API 路由(黑板/Daemon/SSE/项目)
│   ├── 静态文件服务(frontend/dist/
│   └── SSE 推送端点(/api/events
├── asyncio background task: Daemon ticker30s
├── asyncio background task: Inbox watcher1s 轮询)
├── Agent spawn: asyncio.create_subprocess_exec(异步非阻塞)
└── ActiveAgentCounterasyncio.Semaphore

纯 asyncio 单线程。 Daemon ticker、API、SSE、Agent spawn 全部在同一个 asyncio event loop 中,无同步阻塞调用。Full Agent spawn 用 asyncio.create_subprocess_exec(不 await 完成),Subagent 用 Gateway 内部 API。不新增 PM2 进程。


3. 多项目数据布局

~/.sanguo_projects/sanguo_moziplus_v2/
├── projects/
│   ├── _registry.yaml                      ← 全局注册表(YAML,人可读,Git 版本管理)
│   ├── sanguo_quant_live/
│   │   ├── blackboard.db                  ← per-project 黑板
│   │   ├── config/
│   │   │   └── project.yaml               ← per-project 配置覆盖
│   │   ├── artifacts/                     ← per-project 产出物
│   │   │   └── {task-id}/
│   │   │       ├── outputs/
│   │   │       ├── reviews/
│   │   │       ├── archive/
│   │   │       └── data/
│   │   └── experiences/                   ← per-project 经验库
│   │   └── skills/                        ← per-project Skill 覆盖/扩展
│   ├── sanguo_vnpy/
│   │   └── ...
│   └── _archived/                         ← 归档项目(只读)
│       └── old_project/
│
├── inbox/
│   └── daemon.jsonl                       ← Inbox 事件推送
│
├── skills/                                ← 全局 Skill 库
│   ├── builtins/                          ← 系统内置 Skill
│   │   ├── blackboard_operations/
│   │   ├── code_review/
│   │   └── data_validation/
│   └── custom/                            ← 蒸馏产出/用户创建 Skill
│       └── {skill_id}/
│           ├── SKILL.md                   ← 四要素
│           ├── template.md                ← 可选详细模板
│           └── meta.yaml                  ← 版本/来源/tag
│
├── config/
│   ├── default.yaml                       ← 全局默认配置
│   ├── guardrails.yaml
│   ├── template_components.yaml
│   └── review_protocols/
│       ├── plan_review.yaml
│       ├── output_review.yaml
│       ├── analysis_review.yaml
│       └── final_review.yaml
│
├── prompt_templates/                      ← L2 模板(全局共享)
├── schemas/                               ← Schema 校验(全局共享)
└── src/                                   ← 代码

物理隔离:每个项目的 blackboard.db 完全独立。一个项目数据库损坏不影响其他项目。


4. PM2 配置

// ecosystem.config.cjs
module.exports = {
  apps: [{
    name: 'sanguo-moziplus-v2',
    script: '~/.sanguo_projects/sanguo_moziplus_v2/.venv/bin/uvicorn',
    args: 'src.main:app --host 0.0.0.0 --port 8083',
    cwd: '~/.sanguo_projects/sanguo_moziplus_v2',
    interpreter: 'none',
    autorestart: true,
    max_restarts: 10,
    restart_delay: 3000,
    watch: false,
    env: {
      PYTHONPATH: '~/.sanguo_projects/sanguo_moziplus_v2',
      BLACKBOARD_ROOT: '~/.sanguo_projects/sanguo_moziplus_v2/projects',
      INBOX_PATH: '~/.sanguo_projects/sanguo_moziplus_v2/inbox/daemon.jsonl',
      LOG_LEVEL: 'INFO',
    },
    out_file: '~/.sanguo_projects/sanguo_moziplus_v2/logs/daemon.out.log',
    error_file: '~/.sanguo_projects/sanguo_moziplus_v2/logs/daemon.err.log',
  }]
}

5. 配置体系

5.1 全局配置(default.yaml

daemon:
  tick_interval: 30          # Tick 间隔(秒)
  task_timeout: 600          # 单任务超时(秒,10分钟)
  max_global_agents: 5       # 全局最大并发 Agent
  max_per_agent: 1           # 每 Agent 最大并发(默认 sequential
  zombie_threshold: 20       # 连续 N tick 无变更 → 告警

inbox:
  path: "inbox/daemon.jsonl"
  watch_interval: 1          # Inbox 轮询间隔(秒)
  max_size_bytes: 1048576    # 1MB 触发 truncate

review:
  default_max_rounds: 3
  debate_max_rounds: 5
  confidence_threshold: 0.7  # 低于此值升级庞统

experience:
  distill_threshold: 5       # 同 tag 积累 N 条触发二级蒸馏
  expire_days: 30            # 30天无引用 → deprecated

logging:
  level: INFO
  max_file_size: 10MB

5.2 Per-project 配置覆盖

# projects/{project_id}/config/project.yaml
project:
  name: "量化实战项目"
  description: "sanguo_quant_live"
  agents:
    - pangtong-fujunshi
    - simayi-challenger
    - zhangfei-dev
    - guanyu-dev
    - zhaoyun-data
    - jiangwei-infra
  max_global_agents: 3       # 覆盖全局默认
  context:
    nas_path: "/Volumes/stock/"
    backtest_service: "http://192.168.2.154:8088"
    frameworks:
      - "vnpy"
      - "sanguo_vnpy"

6. 部署流程

6.1 首次部署

# 1. 创建安装目录
mkdir -p ~/.sanguo_projects/sanguo_moziplus_v2/{projects,inbox,logs,config}

# 2. 同步代码(从开发目录)
rsync -av --exclude='.venv' --exclude='node_modules' --exclude='.git' \
  ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/ \
  ~/.sanguo_projects/sanguo_moziplus_v2/

# 3. 安装 Python 依赖
cd ~/.sanguo_projects/sanguo_moziplus_v2
python3 -m venv .venv
.venv/bin/pip install fastapi uvicorn pyyaml

# 4. 构建前端
cd src/frontend && npm install && npm run build && cd ../..

# 5. 启动 PM2
pm2 start ecosystem.config.cjs

# 6. 验证
curl http://127.0.0.1:8083/api/daemon/status
curl http://127.0.0.1:8083/  # 前端页面

6.2 日常更新

# 1. 同步代码
rsync -av --exclude='.venv' --exclude='node_modules' --exclude='.git' \
  ~/.openclaw/sanguo_projects/sanguo_moziplus_v2/ \
  ~/.sanguo_projects/sanguo_moziplus_v2/

# 2. 如果前端有变更
cd ~/.sanguo_projects/sanguo_moziplus_v2/src/frontend && npm run build && cd ../..

# 3. 重启
pm2 restart sanguo-moziplus-v2

# 4. 验证
curl http://127.0.0.1:8083/api/daemon/status

6.3 创建项目

# 通过 CLI 创建
python3 src/cli/admin.py project create \
  --name "量化实战" \
  --id "sanguo_quant_live" \
  --agents "pangtong-fujunshi,simayi-challenger,zhangfei-dev,guanyu-dev,zhaoyun-data,jiangwei-infra"

# 自动创建 projects/sanguo_quant_live/ 目录和 blackboard.db

7. 回滚方案

场景 回滚方式
v2 启动失败 pm2 stop sanguo-moziplus-v2v1 (8082) 不受影响
Daemon tick 异常 API POST /api/daemon/stop 停 ticker 不停服务
单项目数据库损坏 删除该项目的 blackboard.db,重启自动重建
全局不可用 v1 仍在 8082 运行,切换回 v1
前端构建失败 回退 dist/ 目录到上一版 Git commit

v1 和 v2 完全独立。v2 出问题直接停掉,v1 继续服务。


8. 监控

8.1 健康端点

GET /api/daemon/status
{
  "ticker_running": true,
  "last_tick": "2026-05-16T23:00:00",
  "tick_interval_seconds": 30,
  "projects": {
    "sanguo_quant_live": {
      "active_agents": 2,
      "tasks_summary": {"pending": 3, "working": 1, "review": 1, "done": 15},
      "db_size_bytes": 45056
    }
  },
  "inbox_pending": 0,
  "active_sessions": 2
}

8.2 逻辑健康自检

Daemon 每 tick 检查:连续 N tick(默认 20,即 10 分钟)无任何任务状态变更 → 写 observation 告警 + 通知用户。

PM2 只能检测进程崩溃,逻辑死循环/卡死需要应用层检测。

8.3 日志

# Tick 日志
pm2 logs sanguo-moziplus-v2 --lines 100 | grep "Tick"

# Agent spawn 日志
pm2 logs sanguo-moziplus-v2 --lines 100 | grep "Spawning"

# 审查日志
pm2 logs sanguo-moziplus-v2 --lines 100 | grep "review\|rebuttal"

8.4 SSE 推送监控

前端通过 /api/events SSE 接收实时事件。推送 4 级:

级别 图标 场景
🔴 紧急 任务失败/系统异常 立即推
🟡 需关注 任务超时/审查不通过 实时推
🟢 日常 任务完成/日报 批量推
🔵 可选 Agent 活动日志 用户订阅

9. 安全

项目 措施
SQLite 文件权限 blackboard.db owner-only 读写(0600
API 认证 内网环境,暂不认证;后续可加 API Key
CLI 限制 blackboard.py 只能本地 exec,不暴露网络
Agent 权限 SOUL.md 约束 + claim assignee 检查
项目隔离 per-project SQLite 物理隔离,一个 WHERE 漏掉也不会跨项目
Session 清理 fcntl 文件锁保护 sessions.json 编辑
归档安全 项目归档前必须无 working 状态任务

10. 性能预估

指标 预估值 理由
Tick 耗时 <50ms 单项目 <10 张表几十条记录
Agent spawn 延迟 2-5s openclaw agent 冷启动
并发 Agent 数 ≤5(全局) ActiveAgentCounter 控制
项目数上限 ~20 SQLite 单文件无压力,PM2 不新增进程
Inbox 文件大小 <200KB 每秒 truncate,崩溃积压 ~200KB/1000条
blackboard.db 大小 <5MB/项目 每任务几 KB,含 experiences
前端首屏加载 <2s Vite 构建优化 + 本地网络

11. v1 → v2 迁移计划

Phase 1: v2 后端验证(v1 不动)
  ├── v2 部署到 8083
  ├── CLI 验证全流程
  └── E2E 测试通过

Phase 2: v2 前端验证
  ├── 前端构建部署
  ├── Dashboard 功能验证
  └── SSE 推送验证

Phase 3: 并行运行
  ├── v1 继续服务(8082)
  ├── v2 接受新任务(8083)
  └── 对比 v1/v2 行为一致性

Phase 4: v1 下线
  ├── pm2 stop sanguo-moziplus
  ├── pm2 delete sanguo-moziplus
  ├── v2 可选接管 8082
  └── v1 代码和数据库保留只读(历史归档)

Phase 5: Mail 逐步下线(远期目标,与黑板评论长期共存)
  ├── v2 上线后 Mail 和黑板评论并行
  ├── 所有 Agent 的 Skill 更新支持黑板评论后逐步关闭 Mail poller
  └── 最终只保留 Mail 作为外部通知通道

12. 交付检查清单

P1 部署前逐项验证:

  • 项目创建、git init、远程配置完成
  • PM2 配置正确,pm2 start 成功
  • 全局注册表 _registry.yaml 可读写,项目列表正确
  • CLI admin.py project create 创建项目成功
  • per-project blackboard.db 自动创建且 schema 正确(含 reviews/experiences/comments.comment_type
  • CLI blackboard.py read/claim/output/comment/decide/observe/create/review 全部可用
  • Daemon tick 30s 循环正常运行
  • Inbox JSONL watcher 正常消费 + truncate
  • Agent spawn 成功(Popen 非阻塞 + sessions_spawn
  • Session 完成后自动存档
  • ActiveAgentCounter 并发控制生效
  • API 端点全部可用(/api/projects/ /api/daemon/ /api/events
  • SSE 推送正常工作
  • 前端构建产物可访问(8083 端口)
  • 健康端点返回正确状态
  • 逻辑健康自检(连续 20 tick 无变更→告警)
  • v1 (8082) 不受 v2 (8083) 影响