马小龙 38326506f0 feat: modernize platform and add datasource pools 5 日 前
..
datasources 38326506f0 feat: modernize platform and add datasource pools 5 日 前
postgres 38326506f0 feat: modernize platform and add datasource pools 5 日 前
.env.example 38326506f0 feat: modernize platform and add datasource pools 5 日 前
README.md 38326506f0 feat: modernize platform and add datasource pools 5 日 前
backend.Dockerfile 38326506f0 feat: modernize platform and add datasource pools 5 日 前
docker-compose.yml 38326506f0 feat: modernize platform and add datasource pools 5 日 前
frontend.Dockerfile 38326506f0 feat: modernize platform and add datasource pools 5 日 前
nginx.conf 38326506f0 feat: modernize platform and add datasource pools 5 日 前

README.md

DataOps Platform 本地隔离测试环境

本目录启动平台 PostgreSQL、两个外部验收数据源、Neo4j、MinIO、n8n、Flask 后端和 Vue 前端。所有数据使用 dataops-test-* Docker 卷,不连接生产服务。

启动

cp deploy/docker/.env.example deploy/docker/.env.local
docker compose --env-file deploy/docker/.env.local \
  -f deploy/docker/docker-compose.yml up -d --build
docker compose -f deploy/docker/docker-compose.yml ps

不需要验证 DeepSeek 或 n8n 管理 API 时,可以不创建 .env.local,直接启动。基础设施和页面仍可使用。

本地地址

能力 地址 / 凭据
前端 http://localhost:18183
后端健康 http://localhost:15500/api/system/health
Neo4j Browser http://localhost:17474neo4j / Passw0rd
MinIO Console http://localhost:19001dataops-test / dataops-test-password
n8n http://localhost:15678
PostgreSQL localhost:15432/dataopsdataops / dataops-test-password
外部 PostgreSQL 数据源 localhost:25432/acceptancesource_reader / source-test-password
外部 MySQL 数据源 localhost:23306/acceptancesource_reader / source-test-password
平台本地登录 首次迁移后按下方命令显式创建;默认验收账号为 admin

平台 PostgreSQL 仅保存平台自身状态;source-postgressource-mysql 模拟由“数据源”定义接入的业务数据库。三者的端口、账号和 Docker 卷相互隔离。

n8n 首次配置

  1. 打开本地 n8n,完成 owner 初始化。
  2. 在 n8n 设置中生成 API Key。
  3. 把 Key 写入未跟踪的 deploy/docker/.env.localN8N_API_KEY=...
  4. 执行 docker compose --env-file deploy/docker/.env.local -f deploy/docker/docker-compose.yml up -d backend

未配置 Key 时,n8n 自身健康检查仍通过,平台 /api/datafactory/health 会返回明确的未配置/未授权状态,不会回退线上地址。

首位管理员

平台不提供自助注册。首次完成数据库迁移后,由部署人员显式创建唯一的首位管理员; 后续账号只能由管理员在用户管理页面创建。密码不会写入 SQL、镜像或日志。

docker compose -f deploy/docker/docker-compose.yml exec -T \
  -e BOOTSTRAP_ADMIN_USERNAME=admin \
  -e BOOTSTRAP_ADMIN_PASSWORD='AdminPass123' \
  backend python -m app.commands.bootstrap_admin --if-missing

AdminPass123 仅是全本地隔离栈的验收样例。非本地环境必须通过密钥注入替换,且 重复执行命令只会跳过,不能覆盖已有管理员。

日常命令

# 状态
docker compose -f deploy/docker/docker-compose.yml ps

# 日志
docker compose -f deploy/docker/docker-compose.yml logs -f backend frontend n8n

# 停止但保留数据
docker compose -f deploy/docker/docker-compose.yml down

# 完全重置本地测试数据(不可恢复)
docker compose -f deploy/docker/docker-compose.yml down -v

数据库迁移与事件一致性

后端容器每次启动时都会先执行 alembic upgrade head,迁移成功后才启动 Gunicorn。初始化 SQL 只负责新测试卷的基础建库;后续结构变化统一由 Alembic 增量迁移管理。

# 查看当前版本
docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  alembic -c alembic.ini current

# 手工升级(正常启动时无需重复执行)
docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  alembic -c alembic.ini upgrade head

# 查看 Outbox 积压、失败数和最老事件年龄(不返回事件载荷)
curl -fsS http://localhost:15500/api/system/health

# 当前阶段尚未注册业务事件处理器;命令会安全退出并保留待处理事件
docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  python -m app.commands.process_outbox

治理对象使用 UUIDv7 作为跨 PostgreSQL、Neo4j、n8n 的稳定标识。核查或补齐 历史 Neo4j 节点前,应先执行只读报告,再显式选择回填:

docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  python -m app.commands.reconcile_governance_uids --ensure-constraints

docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  python -m app.commands.reconcile_governance_uids --backfill --ensure-constraints

冒烟验证

curl -fsS http://localhost:18183/ >/dev/null
curl -fsS http://localhost:18183/api/system/health
curl -fsS http://localhost:15678/healthz

docker compose -f deploy/docker/docker-compose.yml exec -T postgres \
  psql -U dataops -d dataops -c '\\dt public.*'

docker compose -f deploy/docker/docker-compose.yml run --rm minio-init

外部数据源连接池验收

两个外部数据源都会初始化 acceptance_customers 表及 Alpha、Beta 两条固定数据。 以下测试对 PostgreSQL 和 MySQL 分别执行 100 次并发读取,并验证连接复用、最大 并发连接数、空闲回收、重建和删除失效:

PYTHONPATH=. \
TEST_SOURCE_POSTGRES_URL=postgresql://source_reader:source-test-password@127.0.0.1:25432/acceptance \
TEST_SOURCE_MYSQL_URL=mysql+pymysql://source_reader:source-test-password@127.0.0.1:23306/acceptance \
.venv/bin/pytest -q tests/integration/test_datasource_pools.py

运行参数

连接池只管理通过数据源定义接入的外部业务数据库,不管理平台自身的 PostgreSQL。 中型单实例默认值为:基础连接 2、临时溢出 3、取连接等待 10 秒、连接回收 1800 秒、空闲池回收 900 秒、每个 Worker 最多保留 20 个空闲池、查询超时 30 秒。可通过 .env.local 中以下变量调整,服务端会执行上下限校验:

DATASOURCE_POOL_SIZE=2
DATASOURCE_MAX_OVERFLOW=3
DATASOURCE_POOL_TIMEOUT=10
DATASOURCE_POOL_RECYCLE=1800
DATASOURCE_POOL_IDLE_TTL=900
DATASOURCE_MAX_IDLE_POOLS=20
DATASOURCE_QUERY_TIMEOUT=30
DATASOURCE_CREDENTIAL_MASTER_KEY=<Base64 编码的 32 字节密钥>
DATASOURCE_CREDENTIAL_KEY_VERSION=v1
DATASOURCE_CERT_DIR=/etc/dataops-platform/datasource-certs

每个数据源只允许覆盖 pool_sizemax_overflow,其余参数由平台统一控制。 修改连接定义或凭据版本后,旧池进入失效/排空流程,下一次访问按新版本惰性创建。

凭据迁移和一致性核查

先执行只读报告;确认单个 UID 后才允许加密迁移。迁移会先验证密文可解密,再从 Neo4j 删除旧明文:

docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  python -m app.commands.report_datasource_credentials

docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  python -m app.commands.migrate_datasource_credentials \
  --uid <数据源UID> --confirm-encrypt-and-remove-plaintext

docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  python -m app.commands.reconcile_datasource_credentials

docker compose -f deploy/docker/docker-compose.yml exec -T backend \
  python -m app.commands.reconcile_datasource_credentials \
  --repair --uid <数据源UID>

管理员诊断和安全失效

仅管理员可读取 /api/datasource/pools/api/datasource/<UID>/pool,或向 /api/datasource/<UID>/pool/invalidate 提交固定原因 admin_resetconfiguration_changedcredential_rotated。接口只返回池状态和聚合指标, 不返回主机、账号、密文、连接串或配置指纹。强制失效会记录安全审计事件。

故障与恢复演练

默认测试只会跳过,不控制 Docker。显式设置开关后,测试会停止外部 MySQL, 验证三次失败后只对该数据源熔断,并确认外部 PostgreSQL和平台 PostgreSQL继续 可用;随后恢复 MySQL、执行半开探测并验证凭据版本轮换。finally 清理保证 MySQL 一定被重新启动:

RUN_DATASOURCE_OUTAGE_TEST=1 PYTHONPATH=. \
.venv/bin/pytest -q tests/integration/test_datasource_pool_failures.py

若修改了 database/*.sql,已有 PostgreSQL 卷不会自动重放初始化脚本。已存在的 测试环境应新增 Alembic 迁移;只有明确需要丢弃全部本地数据时才执行 down -v

2026-07-16 已验证基线

检查 结果
Compose 服务 backend、frontend、PostgreSQL、Neo4j、MinIO、n8n 均 healthy;minio-init 正常退出 0
HTTP 前端、前端代理的后端健康接口、n8n /healthz 均返回 200
平台健康 PostgreSQL 与 Neo4j 检查为 true,总状态 healthy
本地认证 新 RBAC 管理员 admin / AdminPass123;Argon2id 哈希,不提供注册接口
PostgreSQL 6 张当前业务表和本地 users 表已创建
Neo4j RETURN 1 成功
MinIO dataops-bucket 创建成功
隔离扫描 活跃源码、构建产物、渲染配置与运行日志未发现历史生产服务地址或密钥
数据库迁移 Alembic 基线、治理 UID 与 Outbox 三组迁移可在空库和既有本地库重复执行
跨存储一致性 业务事务与事件同事务回滚;下游中断后可重试恢复;重复投递不重复执行处理器

镜像基线:

  • backend:本仓库构建,Python 3.11,image ID 215df46dacc2
  • frontend:本仓库构建,Node 24 + Nginx 1.27,image ID 42de39689f54
  • PostgreSQL:pgvector/pgvector:pg16(PostgreSQL 16 + vector 扩展)。
  • Neo4j:neo4j:5.26-community
  • MinIO:minio/minio:RELEASE.2025-04-22T22-12-26Z
  • n8n:n8nio/n8n:1.100.1

已知非阻塞技术债:Vue 2 构建仍有 console、CSS 顺序和大包体警告,npm audit 报告 72 个传递依赖问题;这些与 Vue 3/依赖治理阶段统一处理,不在本次业务边界清理中升级。n8n 管理 API 需要完成本地 owner 初始化并配置本地 API Key 后才能验收。未配置 VUE_APP_N8N_CHAT_URL 和预览服务时,聊天助手与文件在线预览失败关闭,不会连接历史线上服务。