⚙️ 第六篇:部署与生产化

第12章 部署与生产化:从本地到上线

H2 与 MySQL 的取舍、Docker 编排、上线前检查清单

12.1 本章导读

前面 11 章把系统里外讲透了,本章解决最后一公里:怎么把它稳定地跑在服务器上。包括数据源的取舍、Docker 编排细节、以及一份可以直接照着打勾的上线检查清单。

12.2 数据源:H2 还是 MySQL

维度H2(standalone profile)MySQL(默认 profile)
部署零依赖,文件库(./data/*.mv.db需独立 MySQL 实例
兼容性MODE=MySQL 兼容模式,共用同一 schema.sql原生
适用本地开发、演示、单机轻量使用生产、联调、多实例共享(未来)
风险文件锁、并发能力有限需运维(备份、连接池、监控)

schema.sql 共 12 张表,sql.init.mode=always 幂等重跑。一个迁移陷阱:schema.sql 用 INSERT ... WHERE NOT EXISTS 只插不更——已存在的配置行(如模型设置)不会被覆盖,下线旧模型需手动 UPDATE。

⚠️ 生产环境别用 H2

本项目曾发生过一次真实误判:在容器沙箱里用 lsof/ps 看不到跨用户的 MySQL 进程,误判"MySQL 没跑"而切了 H2——结果应用连 H2、截图看的是 MySQL,两边数据对不上。判断 MySQL 是否在跑,用 nc -z 127.0.0.1 3306netstat -an | grep LISTEN,别依赖进程列表。

12.3 Docker 部署

项目根目录的 Dockerfile 是多阶段构建:

# 阶段1: maven:3.9-eclipse-temurin-17-alpine 构建
#   - 先 COPY 各模块 pom.xml 跑 dependency:go-offline(利用层缓存)
#   - 再 COPY 全部源码 mvn package -DskipTests
# 阶段2: eclipse-temurin:17-jre-alpine 运行
#   - 只 COPY fat jar,EXPOSE 8090
#   - ENTRYPOINT 默认 standalone profile

docker-compose.yml 的关键挂载与环境变量:

services:
  app:
    build: .
    ports: ["8090:8090"]
    environment:
      - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-sk-local}
      - SPRING_PROFILES_ACTIVE=standalone
    volumes:
      - ./data:/app/data            # H2 数据持久化
      - ./plugins:/app/plugins      # 插件目录
      - ./workspaces:/app/workspaces # Agent 工作区
    restart: unless-stopped
💡 用 MySQL 跑容器

去掉 SPRING_PROFILES_ACTIVE=standalone,改用 SPRING_DATASOURCE_URL/USERNAME/PASSWORD 环境变量指向外部 MySQL 即可。注意容器内访问宿主机 MySQL 要用 host.docker.internal(Mac/Windows)或宿主机内网 IP(Linux)。

12.4 上线检查清单

  • 认证:配置 harness.auth.api-keys(为空则全放行!);服务不直接暴露公网,前置网关
  • 密钥:模型 API Key 走环境变量/密钥管理系统,绝不硬编码进 yml 提交仓库
  • 审批:确认 required-tools 覆盖 shell_execute/fs_write/plugin.run/subprocess.spawn;评估是否启用运行期审批 gate
  • 沙箱:评估 harness.sandbox.default-mode;用容器/低权限 OS 用户隔离
  • 数据库:外部 MySQL + 连接池配置 + 备份 + 事件表归档策略(事件表会持续增长)
  • 可观测:接日志采集、Metrics(/actuator 默认公开,注意加保护)、Tracing、审计
  • 资源:关注无界线程池(ReactLoopAgent.kick 用 newCachedThreadPool),必要时改有界
  • 横向扩展:当前是单实例设计——Agent 内存状态、任务锁、会话亲和性都需处理后才能多实例

12.5 配置项速查表

配置项默认生产建议
server.port8090按需
harness.auth.api-keys空(全放行)必须配置
harness.llm.deepseek.base-url127.0.0.1:8777/v1指向生产网关
harness.llm.deepseek.api-key${DEEPSEEK_API_KEY:}环境变量注入
harness.approval.required-toolsshell/fs_write/plugin.run/subprocess按需收紧
harness.sandbox.default-modeWORKSPACE_WRITE生产考虑 READ_ONLY 起步
harness.agent.temperature空(不发送)网关只接受 temperature=1 时保持为空
harness.extensions.skills.roots./skills新增目录前确认来源可信
harness.extensions.mcp.servers内置 Baidu SSE 示例校验传输、URL、命令与密钥
harness.extensions.plugins.preset内置 Node 与 Java 示例生产只保留必要插件

12.6 小结与下一章预告

本章要点:H2 用于开发演示、MySQL 用于生产;Harness 运行配置统一在 harness.yml;Docker 多阶段构建 + 三个关键挂载卷;上线检查清单覆盖认证/密钥/审批/沙箱/数据库/可观测/资源/扩展八大项;schema.sql 只插不更是迁移陷阱。

下一章:系统的已知边界是什么?想继续深入该往哪个方向走?第13章给出完整的边界清单与进阶路线。