企业级 Java ETL 平台架构设计方案
本方案基于云原生与微服务架构理念,采用前后端分离模式,核心引擎复用成熟的 Kettle (Pentaho Data Integration) 能力,通过 Spring Cloud 生态实现分布式调度、元数据管理及可视化编排 。
- 总体技术栈选型
| 模块层级 | 技术组件 | 选型理由与核心作用 | 来源依据 |
|---|---|---|---|
| 前端交互层 | Vue.js + MXGraph/LogicFlow | 实现拖拽式 DAG 流程设计器,支持可视化节点编排与连线逻辑校验。 | |
| 网关与服务治理 | Spring Cloud Gateway + Nacos/Consul | 统一入口鉴权、流量控制及服务发现,支撑微服务高可用部署。 | |
| 核心业务后端 | Spring Boot + MyBatis Plus | 处理元数据管理、用户权限 (RBAC)、项目协作等业务逻辑。 | |
| ETL 执行引擎 | Pentaho Kettle (PDI) | 作为核心计算内核,支持关系型、NoSQL、大数据等多种数据源的抽取转换加载。 | |
| 任务调度中心 | Quartz / XXL-JOB | 提供分布式定时触发、故障转移及分片广播机制,驱动 ETL 作业执行。 | |
| 元数据存储 | MySQL (主从) + Redis (哨兵) | MySQL 存储作业定义、日志及配置;Redis 缓存热点元数据及分布式锁。 | |
| 实时监控通信 | WebSocket | 建立前端与后端的长连接,实时推送任务运行状态、日志流及进度百分比。 | |
| 部署运维 | Docker + Kubernetes | 容器化封装执行节点,实现弹性伸缩与资源隔离。 |
- 核心架构设计逻辑
平台采用四层微服务架构:展现层 (Vue 前端)、服务层 (Spring Cloud 业务微服务)、引擎层 (Kettle 执行集群)与数据层(元数据与业务数据)。
- 元数据驱动执行模型:所有 ETL 作业(Job/Transformation)均以 XML/KTR 文件形式或 JSON 描述存储在数据库中,执行时由后端动态解析并下发至执行节点,实现"设计态"与"运行态"分离 。
- 分布式执行机制:通过 HTTP 协议或消息队列连接多个无状态 Kettle 执行节点(Worker),主控节点(Master)负责分发任务,支持多节点并行执行以提升吞吐量 。
- 可视化 DAG 编排:前端利用图形库将业务逻辑转化为有向无环图(DAG),后端将其序列化为 Kettle 可识别的配置文件,实现零代码/低代码开发 。
- 核心功能模块代码实现示例
3.1 动态任务调度与执行封装 (Java)
基于 Spring 封装 Kettle 引擎,实现任务的动态加载与参数注入。
java
package com.etl.platform.engine.core;
import org.pentaho.di.core.KettleEnvironment;
import org.pentaho.di.job.Job;
import org.pentaho.di.job.JobMeta;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* Kettle 引擎执行器封装
* 负责初始化环境、加载元数据并启动作业或转换
*/
@Component
public class KettleExecutor {
// 静态代码块初始化 Kettle 环境,确保只执行一次
static {
try {
KettleEnvironment.init(); } catch (Exception e) {
throw new RuntimeException("Kettle 环境初始化失败", e);
}
}
/**
* 执行 Kettle 转换 (Transformation)
* @param transMeta 转换元数据对象
* @param params 运行时参数映射
* @return 执行结果状态
*/
public ExecutionResult executeTransformation(TransMeta transMeta, Map<String, String> params) {
try {
Trans trans = new Trans(transMeta);
// 注入动态参数,支持多租户或分区处理
if (params != null) {
for (Map.Entry<String, String> entry : params.entrySet()) {
trans.setVariable(entry.getKey(), entry.getValue());
}
}
trans.prepareExecution(null);
trans.startThreads();
trans.waitUntilFinished();
if (trans.getErrors() > 0) {
return ExecutionResult.failed("转换执行存在错误");
}
return ExecutionResult.success("转换执行成功");
} catch (Exception e) {
return ExecutionResult.failed("执行异常:" + e.getMessage());
}
}
/**
* 执行 Kettle 作业 (Job)
* 适用于包含多个步骤、邮件通知等复杂控制流的场景
*/
public ExecutionResult executeJob(JobMeta jobMeta, Map<String, String> params) {
try {
Job job = new Job(null, jobMeta);
if (params != null) {
for (Map.Entry<String, String> entry : params.entrySet()) {
job.setVariable(entry.getKey(), entry.getValue());
}
}
job.run();
job.waitUntilFinished();
if (job.getErrors() > 0) {
return ExecutionResult.failed("作业执行存在错误");
}
return ExecutionResult.success("作业执行成功");
} catch (Exception e) {
return ExecutionResult.failed("作业执行异常:" + e.getMessage());
}
}
// 内部结果类定义
public static class ExecutionResult {
private boolean success;
private String message;
public static ExecutionResult success(String msg) {
ExecutionResult r = new ExecutionResult();
r.success = true;
r.message = msg;
return r;
}
public static ExecutionResult failed(String msg) {
ExecutionResult r = new ExecutionResult();
r.success = false;
r.message = msg;
return r;
}
}
}
3.2 分布式任务调度配置 (Quartz/Spring)
配置分布式调度策略,确保高可用环境下任务不重复执行。
yaml
# application.yml 配置片段
spring:
quartz:
job-store-type: jdbc # 使用 JDBC 存储任务状态,支持集群
properties:
org:
quartz:
scheduler:
instanceId: AUTO # 自动生成实例 ID
instanceName: EtlSchedulerCluster
jobStore:
isClustered: true # 开启集群模式
clusterCheckinInterval: 5000
threadPool:
threadCount: 20
java
package com.etl.platform.scheduler.config;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
/**
* 定时任务配置类
* 基于 Quartz 实现分布式调度,配合数据库锁机制防止多节点重复执行
*/
@Configuration
public class SchedulerConfig {
/**
* 定义 ETL 执行任务详情
* 指定具体的 Job 类,该类将调用 KettleExecutor 执行实际逻辑
*/
@Bean
public JobDetailFactoryBean etlJobDetail() {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(EtlExecutionJob.class); // 继承 QuartzJobBean的具体实现类
factory.setDurability(true);
factory.setRequestsRecovery(true); // 支持故障恢复 return factory; }
/**
* 定义触发器
* 支持 Cron 表达式,实现灵活的时间调度策略
*/
@Bean
public SimpleTriggerFactoryBean etlTrigger() {
SimpleTriggerFactoryBean trigger = new SimpleTriggerFactoryBean();
trigger.setJobDetail(etlJobDetail().getObject());
trigger.setStartDelay(0);
trigger.setRepeatInterval(60000); // 示例:每分钟执行一次,实际应使用 CronTrigger
trigger.setName("DailyEtlTrigger");
return trigger;
}
}
3.3 元数据实体设计 (MyBatis/JPA)
定义 ETL 作业的核心元数据结构,用于持久化流程定义。
sql
-- 数据库表结构设计 (MySQL)
-- 存储 ETL 作业的基本信息与版本控制
CREATE TABLE `etl_job_definition` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
`job_code` varchar(64) NOT NULL COMMENT '作业唯一编码',
`job_name` varchar(128) NOT NULL COMMENT '作业名称',
`job_type` tinyint(4) NOT NULL COMMENT '类型:1-转换 (Trans), 2-作业 (Job)',
`engine_version` varchar(32) DEFAULT '9.2' COMMENT 'Kettle 引擎版本',
`content_xml` longtext COMMENT 'Kettle 原始 XML 内容或 JSON 流程定义',
`dag_config` json DEFAULT NULL COMMENT '前端可视化 DAG 布局配置', `status` tinyint(4) DEFAULT '0' COMMENT '状态:0-停用,1-启用',
`cron_expression` varchar(64) DEFAULT NULL COMMENT '调度 Cron 表达式',
`created_by` bigint(20) DEFAULT NULL COMMENT '创建人 ID',
`created_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_job_code` (`job_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ETL 作业定义表';
-- 执行日志表,用于追踪每次运行状态
CREATE TABLE `etl_job_execution_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_id` bigint(20) NOT NULL COMMENT '关联作业 ID',
`batch_no` varchar(64) NOT NULL COMMENT '批次号',
`start_time` datetime DEFAULT NULL COMMENT '开始时间',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
`status` tinyint(4) DEFAULT '0' COMMENT '执行状态:0-运行中,1-成功,2-失败',
`error_msg` text COMMENT '错误堆栈信息',
`rows_read` bigint(20) DEFAULT '0' COMMENT '读取行数',
`rows_written` bigint(20) DEFAULT '0' COMMENT '写入行数',
PRIMARY KEY (`id`),
KEY `idx_job_id` (`job_id`),
KEY `idx_batch_no` (`batch_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ETL 执行日志表';
- 关键实施路径确认
在正式进入详细编码前,需确认以下核心设计决策是否符合您的预期:
- 引擎策略 :是否确认直接集成 Kettle (PDI) 作为底层执行内核?(优势:生态成熟、支持源多;劣势:JVM 内存占用较高,需配合容器化优化)。若需完全自研轻量级算子,架构复杂度将显著增加。
- 调度模式 :采用 Quartz 集群模式 还是对接现有的 XXL-JOB分布式调度中心?前者集成度高,后者运维监控更完善 。
- 可视化深度 :前端 DAG 编辑器是仅做配置生成 (生成 Kettle XML),还是需要实现独立执行引擎(解析 JSON 自行调度)?推荐方案为前者,以复用 Kettle 强大的转换能力 。
- 数据一致性 :对于分布式执行产生的日志和状态,是否接受最终一致性(通过异步消息更新状态),还是要求强一致性(影响并发性能)?
请针对上述四点进行确认或提出调整意见,确认后我将输出详细的数据库 ER 图、API 接口定义及完整的前后端工程结构。