# visual-etl-backend **Repository Path**: wayleq/visual-etl-backend ## Basic Information - **Project Name**: visual-etl-backend - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-26 - **Last Updated**: 2026-07-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # visual-etl-backend `visual-etl-backend` 是 Visual ETL 项目的 Spring Boot 后端服务,负责数据源治理、元数据中心、可视化 ETL 画布生命周期、算子执行引擎、资产授权、公开 API 与平台运维。 ## 技术栈 | 层次 | 技术 | |---|---| | 运行时 | Java 21、Spring Boot 4.1.0 | | Web / 安全 | Spring Web、Spring Security、Servlet Session、Cookie CSRF | | 数据访问 | MyBatis-Plus 3.5.17、JPA 注解(用于实体映射)、MySQL 8.4 / Oracle / Doris | | 迁移 | Flyway(MySQL 方言),启动时预检 + 自动修复 | | 缓存 / 会话 | Redis(Spring Data Redis) | | 可观测 | Spring Boot Actuator(health / info / probes) | | 测试 | Spring Boot Test、H2 内存数据库 | | 前端集成 | frontend-maven-plugin 在 `generate-resources` 阶段构建 Vue 3 产物到 `src/main/resources/static` | ## 模块结构 主包为 `com.visualetl`,入口类 `VisualEtlApplication` 启用:`@SpringBootApplication`、`@EnableScheduling`、以及 `@MapperScan(markerInterface = BaseRepository.class)` 扫描 MyBatis-Plus Mapper。 ```text com.visualetl ├── assetauth # 资产授权:用户/角色/服务账号 + 数据范围 + 授权判定 ├── audit # 请求关联与审计日志 ├── authorization # 平台角色、权限码、用户角色绑定 ├── backup # 备份与恢复 ├── bi # BI 数据集、图表、大屏资产 ├── common # 基础工具、BaseRepository 标记接口 ├── config # Spring 配置:Security、Flyway 恢复、ObjectMapper、过滤器 ├── connector # JDBC 连接器与 DatabaseMetaData 元数据发现 ├── datasource # 数据源生命周期:增删改查、连接测试、激活、凭据轮换、禁用影响预览 ├── diagnostic # 诊断包与日志脱敏 ├── embedding # 向量模型与知识库向量存储 ├── execution # ETL 执行引擎:提交、DAG 编排、节点执行、取消、重试、恢复 ├── job # ETL 作业画布:草稿、Agent 生成、校验、预览、发布、版本、回滚 ├── knowledge # 知识库文档摄入与检索 ├── metadata # 元数据中心:表/列资产、采集任务、快照、影响分析 ├── migration # Flyway 迁移预检、失败分类、健康指标 ├── operations # 平台运维与设置 ├── operator # 算子注册中心、文件算子热加载、后端算子执行器 ├── publicapi # 公开 API、Webhook、限流、幂等、任务服务 ├── question # 数据问答 ├── retention # 审计与数据保留策略 ├── security # 安全过滤器:强制改密、绝对会话超时 ├── serviceaccount # 服务账号与 Bearer Token 认证 ├── settings # 平台设置:LLM、Embedding、安全、运行时参数 ├── skill # Skills 管理与规则提炼 └── user # 用户、密码策略、管理员初始化 ``` ## 核心架构 ### 1. 数据源与元数据中心 - 支持 `MYSQL`、`ORACLE`、`DORIS` 三类数据源;每个数据源有 `environment` 字段标识环境(如 `DEV / TEST / PROD`,默认 `DEV`)。 - 页面录入的密码经 AES-256-GCM 加密落库,也支持 `env://变量名` 引用外部凭据。 - 数据源必须先“激活”才能被元数据采集;禁用前提供影响预览,避免被 ETL 作业或 BI 资产依赖。 - 元数据采集为异步任务模型(`QUEUED → DISCOVERING → VALIDATING → PUBLISHING`),超时与取消均可控。 - 采集结果通过 `MetadataSnapshotPublisher` 发布为快照,元数据 API 默认只返回当前用户有读权限的数据源资产。 主要入口: - `DataSourceController`:`/api/datasources` - `MetadataController`:`/api/metadata` - `MetadataCatalogController`:目录与快照浏览 - `MetadataImpactController`:元数据变更影响分析 ### 2. 算子模型与热加载 算子 `EtlOperator` 是前后端统一的资产: - `executionSide`:`FRONTEND`(仅在前端画布渲染)或 `BACKEND`(由后端执行引擎运行)。 - `configSchema`:前端表单 JSON Schema。 - `implementation`:后端执行器类型(`handlerType`)或前端组件信息。 - `inputPorts / outputPorts`:节点连线端口定义。 算子来源: 1. **数据库算子**:通过 `OperatorController` 导入/导出/管理,`source=DB`。 2. **文件算子**:启动时从 `./operators/*.operator.json` 加载,`source=FILE`,支持 WatchService 防抖热重载。 文件算子由 `FileOperatorLoader` 管理: - 配置文件:`visual-etl.operator-file.*` - 监听目录变更,防抖默认 1000ms,自动同步到 `etl_operator` 表。 - 文件算子与 DB 算子独立,删除文件后对应算子会被清理。 后端执行器通过 `BackendOperatorRegistry` 按 `handlerType` 路由,已实现的示例包括: - `dbSource`:数据库源节点 - `csvSource`:CSV 文件源 - `filterRows`:行过滤 - `schemaMapper`:字段映射 - `dataMigrationSink`:数据迁移写入 - `chartDataAggregator`:图表聚合 - `noop`:兜底空执行 ### 3. ETL 画布生命周期 ETL 作业的生命周期由 `EtlJobController` 统一编排: ```text 草稿 (DRAFT) ├── 画布设计 /api/etl-jobs/drafts/{id}/canvas ├── 节点删除影响分析 /api/etl-jobs/drafts/{id}/canvas/nodes/{nodeId}/delete-impact ├── 定义应用 /api/etl-jobs/drafts/{id}/definition ├── Agent 生成 /api/etl-jobs/agent-create, /api/etl-jobs/agent-generations ├── 校验 /api/etl-jobs/{id}/validations ├── 预览 /api/etl-jobs/{id}/previews └── 发布预览 /api/etl-jobs/{id}/publish-previews │ ▼ 发布 (RELEASE) /api/etl-jobs/{id}/releases │ ▼ 运行 (EXECUTION) /api/etl-jobs/{jobId}/executions, /api/etl-jobs/{jobId}/runs ``` - 画布定义使用 DAG(节点 + 边),节点执行前进行拓扑排序。 - 发布时会生成不可变版本(`EtlRelease`),记录 `definitionJson`、`configurationJson` 与 `dependencyDigest`。 - 受管 ETL(`sourceSnapshotId != null`)必须发布后才能执行,确保血缘可追踪。 ### 4. 执行引擎 执行引擎分两层: - `ExecutionService`:接收执行请求、校验并发(默认同主体最多 2 个运行中)、写入执行日志、支持幂等提交。 - `ExecutionOrchestrator`: - 根据画布定义初始化执行上下文与节点执行记录。 - 拓扑排序后逐节点执行。 - `OperatorExecutionService` 负责实际节点运行: claim 节点、解析输入端口、调用后端算子、写回结果。 - 上游失败节点会自动标记下游为 `UPSTREAM_FAILED`。 执行模式: - `PRODUCTION`:允许写入目标。 - `DRY_RUN`:默认最多 100 行,不写入目标。 - 自定义模式通过 `/api/etl-jobs/{jobId}/runs` 传入 `ExecutionSubmissionModels.Request`。 恢复能力: - `ExecutionService.evaluateRetry` / `retry`:支持失败任务安全重试,自动识别成功写入或结果不确定节点,要求先补偿。 - `ExecutionRecoveryService`:为失败执行创建恢复用例、记录补偿操作、支持人工复核。 - 服务启动时 `ExecutionOrchestrator.recover()` 将 `RUNNING` 节点标记为 `INTERRUPTED` 并聚合执行状态。 ### 5. 资产授权 `AssetAuthorizationService` 提供统一的资产级授权: - 资产类型:`DATA_SOURCE`、`ETL_JOB`、`BI_DATASET`、`BI_CHART`、`BI_DASHBOARD`、`KNOWLEDGE_BASE`、`SKILL` 等。 - 操作:`READ`、`CONFIGURE`、`EXECUTE`、`PUBLISH` 等。 - 授权来源: - 管理员角色自动获得全部资产权限。 - 用户直接授权(`GrantSubjectType.USER`)。 - 角色授权(`GrantSubjectType.ROLE`)。 - 服务账号授权(`GrantSubjectType.SERVICE_ACCOUNT`)。 - 数据范围 `DataScope`:可限定到具体数据源、表、模式等,授权判定前校验资产是否匹配范围。 ### 6. 公开 API 与 Webhook - `PublicApiController` 暴露 `/api/v1/tasks`、`/api/v1/assets/{type}`。 - `PublicApiProtectionFilter` 提供源 IP 白名单、限流(Redis/内存降级)、幂等校验。 - `WebhookController` / `WebhookDispatcher` 支持异步可靠 Webhook 分发,可配置允许主机、连接/请求超时、分发延迟。 ### 7. 安全与会话 `SecurityConfig` 配置: - Cookie CSRF Token,名称为 `VE-XSRF-TOKEN`,请求头 `X-VE-XSRF-TOKEN`。 - Service Bearer Token 过滤器,用于服务账号调用,自动绕过 CSRF。 - 绝对会话超时过滤器(默认 8h)。 - 强制改密过滤器:首次登录或管理员标记必须改密。 - Session Fixation 保护、并发会话管理、统一 401/403 Problem Details 响应。 ### 8. 数据库迁移 - Flyway 脚本位于 `src/main/resources/db/migration`,当前约 67 个版本。 - `FlywayRecoveryConfig` 在启动时执行: 1. `MigrationPreflight.verify` 预检未来版本、失败版本、校验和漂移。 2. 若存在 `FAILED_MIGRATION` 且开启 `visual-etl.migration.repair-on-failed`,执行一次 `flyway.repair()` 后重试。 3. 迁移完成后二次校验,确保无 pending 版本。 - `MigrationHealthIndicator` 将迁移状态纳入 `/actuator/health/readiness`。 ## 功能页面 以下是系统主要功能页面截图,按左侧导航顺序排列,便于快速了解各模块界面。 ### 数据工程工作台 ![数据工程工作台](images/ScreenShot_2026-07-26_142955_294.png) ### 数据源 ![数据源](images/ScreenShot_2026-07-26_143316_633.png) ### 数据资产目录 ![数据资产目录](images/ScreenShot_2026-07-26_143324_237.png) ### AI 问数 ![AI 问数](images/ScreenShot_2026-07-26_143336_811.png) ### 智能 BI 分析空间 ![智能 BI 分析空间](images/ScreenShot_2026-07-26_143343_075.png) ### Skills 管理 ![Skills 管理](images/ScreenShot_2026-07-26_143348_524.png) ### 知识库 ![知识库](images/ScreenShot_2026-07-26_143353_649.png) ### 算子中心 ![算子中心](images/ScreenShot_2026-07-26_143358_437.png) ### ETL 管理 ![ETL 管理](images/ScreenShot_2026-07-26_143403_658.png) ### 系统设置 ![系统设置](images/ScreenShot_2026-07-26_143408_978.png) ## 环境配置 核心配置项(可通过环境变量或 `application.yml` 覆盖): | 变量 | 默认值 | 说明 | |---|---|---| | `VISUAL_ETL_DB_URL` | `jdbc:mysql://localhost:3306/visual_etl?...` | 业务数据库 | | `VISUAL_ETL_DB_USERNAME` | `root` | 数据库账号 | | `VISUAL_ETL_DB_PASSWORD` | `root` | 数据库密码 | | `VISUAL_ETL_DB_POOL_SIZE` | `10` | Hikari 连接池上限 | | `VISUAL_ETL_REDIS_HOST` | `localhost` | Redis 主机 | | `VISUAL_ETL_REDIS_PORT` | `6379` | Redis 端口 | | `VISUAL_ETL_REDIS_PASSWORD` | 空 | Redis 密码 | | `VISUAL_ETL_ENCRYPTION_KEY` | `change-me-before-production` | 本地凭据加密密钥,生产必须替换 | | `VISUAL_ETL_ADMIN_BOOTSTRAP_ENABLED` | `false` | 是否自动创建管理员 | | `VISUAL_ETL_ADMIN_INITIAL_PASSWORD` | `VisualEtl@2026` | 管理员初始密码 | | `VISUAL_ETL_SESSION_IDLE_TIMEOUT` | `30m` | 会话空闲超时 | | `VISUAL_ETL_SESSION_ABSOLUTE_TIMEOUT` | `8h` | 会话绝对超时 | | `VISUAL_ETL_SESSION_COOKIE_SECURE` | `true` | Cookie Secure 标志 | | `VISUAL_ETL_OPERATOR_FILE_ENABLED` | `true` | 是否启用文件算子 | | `VISUAL_ETL_OPERATOR_PATH` | `./operators` | 文件算子目录 | | `VISUAL_ETL_OPERATOR_WATCH_ENABLED` | `true` | 是否热加载 | | `VISUAL_ETL_PUBLIC_API_ALLOWED_SOURCES` | `127.0.0.1,::1` | 公开 API 源 IP 白名单 | | `VISUAL_ETL_PUBLIC_API_RATE_LIMIT_PER_MINUTE` | `120` | 公开 API 每分钟限流 | | `VISUAL_ETL_WEBHOOK_ALLOWED_HOSTS` | `webhooks.example.com` | Webhook 允许主机 | ## 构建与运行 ### 开发模式 启动 MySQL 与 Redis: ```powershell docker compose up -d mysql redis ``` 运行后端: ```powershell mvn -pl visual-etl-backend spring-boot:run ``` 服务监听 `http://localhost:8080`,API 前缀 `/api`。 ### 前端一体化打包 ```powershell mvn -pl visual-etl-backend clean package ``` 前端产物会自动写入 `src/main/resources/static`,打包后可单独运行: ```powershell java -jar visual-etl-backend/target/visual-etl-backend-0.1.0-SNAPSHOT.jar ``` 跳过前端构建: ```powershell mvn -pl visual-etl-backend clean package -Dfrontend.skip=true ``` ### 测试 后端使用 H2 内存数据库运行集成测试: ```powershell mvn -pl visual-etl-backend test ``` 关键测试覆盖: - `operator.file.FileOperatorLoaderTest`:文件算子加载与热重载。 - `operator.execution.OperatorExecutionServiceTest`:DAG 执行与节点状态。 - `migration.MigrationStatusIntegrationTest` / `config.FlywayRecoveryConfigTest`:迁移状态与恢复。 - `publicapi.PublicApiContractTest`:公开 API 契约。 - `assetauth.AssetGrantIntegrationTest`:资产授权。 - `datasource.DataSourceLifecycleIntegrationTest`:数据源生命周期。 - `metadata.MetadataCollectionIntegrationTest`:元数据采集。 ## 开发一个文件算子 在 `./operators` 目录下新建 `my-operator.operator.json`: ```json { "code": "my-operator", "name": "我的算子", "category": "TRANSFORM", "executionSide": "BACKEND", "version": "1.0.0", "description": "示例后端算子", "inputPorts": ["rows"], "outputPorts": ["rows"], "configSchema": { "type": "object", "properties": { "threshold": { "type": "number" } } }, "implementation": { "handlerType": "noop" } } ``` - `executionSide` 为 `BACKEND` 时需要后端存在对应 `handlerType` 的 `BackendOperatorExecutor`。 - 保存文件后约 1 秒(`debounce-millis`)自动热加载到数据库,刷新前端算子目录即可使用。 - 删除文件会自动清理对应算子记录。 ## 关键 API 速查 | 路径 | 说明 | |---|---| | `GET /api/datasources` | 数据源列表 | | `POST /api/datasources/{id}/test` | 连接测试 | | `POST /api/metadata/sync/{dataSourceId}` | 触发元数据采集 | | `GET /api/metadata/tables` | 表资产列表 | | `GET /api/etl-jobs` | ETL 作业列表 | | `GET /api/etl-jobs/drafts/{id}/canvas` | 获取画布 | | `PUT /api/etl-jobs/drafts/{id}/canvas` | 保存画布 | | `POST /api/etl-jobs/{id}/validations` | 执行校验 | | `POST /api/etl-jobs/{id}/releases` | 发布版本 | | `POST /api/etl-jobs/{jobId}/executions` | 执行作业 | | `GET /api/etl-executions` | 执行记录 | | `POST /api/etl-executions/{id}/cancel` | 取消执行 | | `POST /api/etl-executions/{id}/retry` | 重试执行 | | `GET /api/operators` | 算子列表 | | `POST /api/operators/import` | 批量导入算子 | | `GET /actuator/health` | 健康检查 | | `GET /actuator/health/readiness` | 就绪探针(含迁移、数据库状态) | ## 注意事项 - 生产环境务必将 `VISUAL_ETL_ENCRYPTION_KEY` 替换为独立随机密钥;更换后无法解密已有本地凭据。 - 已执行的 Flyway 脚本禁止修改;任何数据库变更请新增更高版本脚本。 - 文件算子目录 `./operators` 建议纳入版本控制或部署脚本管理;生产环境可关闭 `watch-enabled` 以避免运行时文件变更。 - 公开 API 默认仅允许本机访问;生产请收紧 `VISUAL_ETL_PUBLIC_API_ALLOWED_SOURCES` 并启用 Redis 限流。