日期:2026-07-18 状态:已完成讨论,等待书面规格审阅
为 DataOps 平台接入的外部业务数据源建立统一、安全、可观测的连接池框架。 第一阶段走通 PostgreSQL 和 MySQL,部署边界为单台服务器、单个后端实例, 并为后续多副本部署保留配置与接口扩展能力。
本设计明确区分两类数据库连接:
DataSource 定义接入的外部数据库。元数据采集、数据预览、
质量检查和 DataFlow 执行通过本设计的连接池管理器访问。postgresql+psycopg2。mysql+pymysql。connect_args 透传。平台控制面
Flask-SQLAlchemy ──> 平台 PostgreSQL
仅使用框架连接管理,不进入 DataSource Pool Registry
业务数据面
DataSource API / 元数据采集 / 数据预览 / DataFlow
│
▼
DataSourceConnectionManager
├── DataSourceDefinitionRepository
├── CredentialProvider
├── PostgreSQLAdapter
├── MySQLAdapter
├── PoolRegistry
├── CircuitBreaker
└── PoolMetrics
│
┌─────────┴─────────┐
▼ ▼
PostgreSQL 数据源池 MySQL 数据源池
业务模块只能通过 DataSourceConnectionManager 获取外部数据库连接,不得直接
读取数据源密码并调用 create_engine()。连接测试是唯一允许创建临时 Engine 的
入口,且必须使用 NullPool 并在完成后执行 dispose()。
每个数据源必须具有稳定 UUID,并以 data_source_uid 作为业务身份。池注册键由
以下内容组成:
data_source_uid
credential_version
connection_config_fingerprint
连接配置指纹由数据库类型、主机、端口、数据库名、Schema 和白名单安全选项生成, 不包含用户名、密码、连接 URL 或密文。
连接池按需创建:
draining,连接归还后再释放。Gunicorn Worker 是独立进程。即使只有一个后端实例,各 Worker 仍拥有独立的 Pool Registry,第一阶段不尝试跨进程共享数据库连接。
单个数据源、单个 Worker 的默认参数:
pool_size=2
max_overflow=3
pool_timeout=10
pool_recycle=1800
pool_pre_ping=true
pool_use_lifo=true
采用 4 个 Worker 时,一个持续繁忙的数据源理论最大连接数为 20,常驻连接数 最大为 8。数据源可以配置受控的池大小覆盖值,但服务端必须限制上下限,不能直接 接受用户提交的任意连接数量。
后续多副本阶段使用以下公式重新计算单数据源连接预算:
副本数 × Worker 数 × (pool_size + max_overflow)
Adapter 负责:
SELECT 1 探测。PostgreSQL 默认启用 TCP keepalive:
connect_timeout=5
keepalives=1
keepalives_idle=30
keepalives_interval=10
keepalives_count=3
MySQL 默认设置:
connect_timeout=5
read_timeout=30
write_timeout=30
charset=utf8mb4
SSL 和证书参数只能从明确白名单读取,不允许任意驱动参数透传。前端传入的
type 必须映射到平台内部 Adapter,不能直接成为 SQLAlchemy driver name。
平台 PostgreSQL 新增 datasource_credentials:
id
data_source_uid
credential_version
encrypted_payload
nonce
key_version
status
created_at
retired_at
encrypted_payload 包含用户名、密码和必要的认证选项。Neo4j DataSource 节点
只保存:
uid
type
host
port
database
schema
credential_ref
credential_version
业务描述和治理属性
凭据使用 AES-256-GCM 加密:
DATASOURCE_CREDENTIAL_MASTER_KEY 环境变量注入。data_source_uid + credential_version 作为附加认证数据。key_version 为后续主密钥轮换保留。API、日志、异常、Neo4j 查询结果和诊断接口均不得返回用户名、密码、密文、
带凭据的 URL 或完整连接串。数据源列表只返回 credential_configured 等布尔状态。
NullPool 临时 Engine 测试连接,随后关闭。credential_version。draining。retired。修改失败时,数据源继续引用原有有效版本。PostgreSQL 与 Neo4j 之间使用现有 Outbox 和补偿巡检实现最终一致性。
revoked。业务模块使用统一的上下文接口:
with data_source_manager.connect(
data_source_uid,
purpose="metadata_preview",
) as connection:
...
管理器依次完成定义读取、凭据获取、Adapter 选择、池注册、连接借出和归还。 业务模块不持有 Engine,不负责连接池配置,也不能访问凭据明文。
purpose 使用平台枚举,第一阶段至少包括:
connection_testmetadata_collectionmetadata_previewquality_checkdataflow_readdataflow_write除 dataflow_write 外默认使用只读事务。写入任务必须显式提交,异常时回滚。
每个数据源独立维护状态:
healthy
degraded
open
draining
closed
healthy,失败继续熔断。DATASOURCE_POOL_TIMEOUT。主要稳定错误码:
DATASOURCE_NOT_FOUNDDATASOURCE_TYPE_UNSUPPORTEDDATASOURCE_CREDENTIAL_UNAVAILABLEDATASOURCE_CONNECTION_FAILEDDATASOURCE_POOL_TIMEOUTDATASOURCE_CIRCUIT_OPENDATASOURCE_QUERY_TIMEOUTDATASOURCE_READ_ONLY_VIOLATION错误响应不包含驱动原始连接 URL 或凭据。
管理员可以查看单个数据源的池摘要:
data_source_uid
database_type
pool_state
pool_size
checked_out
checked_in
overflow
checkout_wait_ms
last_used_at
consecutive_failures
circuit_open_until
credential_version
平台健康检查仅返回聚合数据:
active_pool_count
degraded_pool_count
open_circuit_count
checked_out_total
pool_timeout_total
指标至少覆盖:
所有日志使用数据源 UID 和错误分类;异常文本在写日志前统一脱敏。
迁移必须分两步:
生产执行前必须单独备份 Neo4j 和平台 PostgreSQL。迁移过程不得在日志、报告或 异常中输出明文密码。迁移失败的数据源保持原状态并进入人工核查清单。
现有数据源保存、验证和连接测试接口必须先完成请求日志脱敏。数据源列表接口必须 在凭据迁移前就停止返回密码。
Docker 测试栈新增两个业务数据源服务:
platform-postgres 平台控制库
source-postgres PostgreSQL 验收数据源
source-mysql MySQL 验收数据源
验收标准:
测试包括:
进入多副本阶段后再评估:
第一阶段的 Adapter、CredentialProvider、Pool Registry 和指标接口保持稳定, 多副本阶段不改变业务模块的连接获取接口。