Apache DolphinScheduler任务提交流程:从Web UI到Worker执行全链路

Apache DolphinScheduler任务提交流程:从Web UI到Worker执行全链路

【免费下载链接】dolphinscheduler Apache DolphinScheduler is the modern data orchestration platform. Agile to create high performance workflow with low-code 【免费下载链接】dolphinscheduler 项目地址: https://gitcode.com/gh_mirrors/dolp/dolphinscheduler

在数据处理和工作流调度中,用户最关心的问题莫过于:我的任务究竟是如何从点击"运行"按钮到最终在服务器上执行的? 本文将以Apache DolphinScheduler为原型,详细拆解任务从Web UI提交到Worker节点执行的完整链路,让你一文掌握分布式调度系统的核心运作机制。

一、Web UI提交:用户交互的起点

任务提交的旅程始于用户在Web界面上的操作。DolphinScheduler的前端界面采用Vue.js构建,核心交互逻辑集中在DAG编辑器和流程实例管理模块。

1.1 DAG编辑器的任务配置

当用户在DAG画布上拖拽组件并配置任务属性时,前端会构建一个包含完整任务元数据的JSON对象。关键代码位于DAG编辑器组件中:

src/js/conf/home/pages/dag/_source/dag.vue文件实现了DAG图的渲染和任务配置功能。用户完成配置后,点击"运行"按钮会触发提交逻辑,将任务定义转换为API请求参数。

1.2 提交请求的构建与发送

任务提交的核心逻辑在src/js/conf/home/pages/dag/definitionDetails.vue中实现。该组件会收集以下关键参数:

  • 流程定义ID(processDefinitionCode)
  • 执行策略(failureStrategy)
  • 优先级(processInstancePriority)
  • Worker分组(workerGroup)
  • 环境变量(environmentCode)

这些参数通过Axios发送到后端API,典型的请求示例如下:

this.$http.post(`/projects/${projectCode}/executors/start-process-instance`, {
  processDefinitionCode: this.processDefinitionCode,
  failureStrategy: "CONTINUE",
  processInstancePriority: "MEDIUM",
  workerGroup: "default",
  environmentCode: -1
})

二、API服务层:请求的接收与验证

任务请求首先到达API服务层,这一层负责请求验证、权限检查和参数处理。

2.1 请求入口:ExecutorController

API服务的核心入口是src/main/java/org/apache/dolphinscheduler/api/controller/ExecutorController.java,其中startProcessInstance方法处理任务提交请求:

@PostMapping(value = "start-process-instance")
public Result startProcessInstance(
    @ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
    @PathVariable long projectCode,
    @RequestParam(value = "processDefinitionCode") long processDefinitionCode,
    @RequestParam(value = "failureStrategy", required = true) FailureStrategy failureStrategy,
    // 其他参数...
) {
    // 权限验证和参数校验
    return executorService.startProcessInstance(loginUser, projectCode, processDefinitionCode, ...);
}

2.2 业务逻辑处理:ExecutorService

请求经过验证后,会调用src/main/java/org/apache/dolphinscheduler/api/service/ExecutorService.java的实现类处理核心业务逻辑。主要步骤包括:

  1. 检查用户对项目的操作权限
  2. 验证流程定义的合法性和状态
  3. 创建流程实例记录(ProcessInstance)
  4. 生成命令对象(Command)并写入数据库
public Result startProcessInstance(User loginUser, long projectCode, long processDefinitionCode, ...) {
    // 权限检查
    Project project = projectService.checkProjectAndAuth(loginUser, projectCode, ProjectAction.EXECUTE);
    
    // 获取流程定义
    ProcessDefinition processDefinition = processDefinitionService.findProcessDefinitionByCode(projectCode, processDefinitionCode);
    
    // 创建流程实例
    ProcessInstance processInstance = processInstanceService.createProcessInstance(..., processDefinition, ...);
    
    // 创建并保存命令
    Command command = commandService.createCommand(..., processInstance, ...);
    
    return Result.success(processInstance.getId());
}

三、Master服务:命令分发与任务调度

任务请求在API层完成持久化后,就进入了Master服务的处理流程,这是整个调度系统的核心。

3.1 命令消费:MasterSchedulerService

Master服务通过src/main/java/org/apache/dolphinscheduler/server/master/scheduler/MasterSchedulerService.java定期从数据库拉取命令:

@Override
public void run() {
    while (running) {
        // 从数据库获取命令
        List<Command> commands = commandMapper.queryCommandList(
            ServerConfig.getInstance().getMasterExecThreads(), 
            CommandType.START_PROCESS, 
            CommandType.RECOVER_PROCESS,
            // 其他命令类型...
        );
        
        // 处理命令
        for (Command command : commands) {
            processCommand(command);
        }
        
        // 休眠固定时间后再次拉取
        Thread.sleep(interval);
    }
}

3.2 流程实例执行线程:WorkflowExecuteThread

每个命令会被封装为一个src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteThread.java线程执行:

@Override
public void run() {
    try {
        // 初始化流程执行上下文
        initProcessInstanceContext();
        
        // 构建DAG图
        ProcessDag processDag = generateFlowDag();
        
        // 执行DAG
        processDag.run();
        
    } catch (Exception e) {
        logger.error("workflow execute thread failed", e);
        processInstance.setStatus(ExecutionStatus.FAILURE);
    } finally {
        // 清理资源
    }
}

3.3 DAG执行与任务分发

流程实例线程会解析流程定义生成DAG图,并按照依赖关系依次调度任务节点。当任务满足执行条件时,Master会通过src/main/java/org/apache/dolphinscheduler/server/master/execution/ExecutorDispatcher.java将任务分发到合适的Worker节点:

public Boolean dispatch(final ExecutionContext context) {
    // 根据任务类型选择执行器管理器
    ExecutorManager executorManager = executorManagers.get(context.getExecutorType());
    if (executorManager == null) {
        logger.error("can not find executor manager for type: {}", context.getExecutorType());
        return false;
    }
    
    // 执行任务分发
    return executorManager.execute(context);
}

3.4 Worker节点选择:HostManager

在分发任务前,Master需要选择合适的Worker节点。DolphinScheduler提供了多种节点选择策略,默认实现是src/main/java/org/apache/dolphinscheduler/server/master/selector/CommonHostManager.java

@Override
public Host select(ExecutionContext context) {
    // 根据Worker分组获取可用节点列表
    List<HostWorker> hostWorkers = workerNodeManager.getAvailableWorkerList(context.getWorkerGroup());
    
    // 根据选择策略选择节点
    HostSelector selector = HostSelector.of(masterConfig.getHostSelector());
    HostWorker selected = selector.select(hostWorkers);
    
    return new Host(selected.getHost(), selected.getPort());
}

四、Worker服务:任务接收与执行

任务经过Master调度后,最终会发送到选定的Worker节点执行。

4.1 任务接收:Netty服务

Worker节点通过src/main/java/org/apache/dolphinscheduler/server/worker/netty/WorkerNettyServer.java监听并接收Master发送的任务请求。任务请求由src/main/java/org/apache/dolphinscheduler/server/worker/processor/TaskExecuteProcessor.java处理:

@Override
public void process(Channel channel, Command command) {
    try {
        // 解析命令内容
        TaskExecutionContext context = JSONUtils.parseObject(command.getBody(), TaskExecutionContext.class);
        
        // 创建任务执行线程
        TaskExecuteThread taskExecuteThread = new TaskExecuteThread(context);
        
        // 提交到线程池执行
        workerExecService.submit(taskExecuteThread);
        
        // 发送ACK响应
        sendAck(channel, command, context.getTaskInstanceId());
    } catch (Exception e) {
        logger.error("process task execute command error", e);
    }
}

4.2 任务执行线程:TaskExecuteThread

每个任务会由独立的src/main/java/org/apache/dolphinscheduler/server/worker/runner/TaskExecuteThread.java线程执行:

@Override
public void run() {
    // 初始化任务执行上下文
    TaskExecutionContext context = buildTaskExecutionContext();
    
    // 更新任务状态为运行中
    taskInstanceService.updateTaskInstanceStatus(context.getTaskInstanceId(), ExecutionStatus.RUNNING);
    
    try {
        // 创建任务执行器
        AbstractTask task = TaskManagerFactory.newInstance(context);
        
        // 执行任务
        task.run();
        
        // 更新任务状态为成功
        taskInstanceService.updateTaskInstanceStatus(context.getTaskInstanceId(), ExecutionStatus.SUCCESS);
        
    } catch (Exception e) {
        logger.error("task execute failed", e);
        // 更新任务状态为失败
        taskInstanceService.updateTaskInstanceStatus(context.getTaskInstanceId(), ExecutionStatus.FAILURE);
    }
}

4.3 任务执行器:Task实现类

不同类型的任务由不同的执行器实现,例如Shell任务的执行器是src/main/java/org/apache/dolphinscheduler/server/worker/task/shell/ShellTask.java

@Override
public void run() {
    // 创建进程执行器
    ProcessExecutor processExecutor = new ProcessExecutor();
    
    // 构建命令行
    String command = buildCommand();
    
    // 执行命令并获取结果
    ProcessResult result = processExecutor.execute(command, 
                                                  context.getTaskProps().getTaskTimeout(),
                                                  logHandler);
    
    // 处理执行结果
    handleResult(result);
}

4.4 任务结果回调

任务执行完成后,Worker会将结果通过Netty发送回Master,由src/main/java/org/apache/dolphinscheduler/server/master/processor/TaskResponseProcessor.java处理:

@Override
public void process(Channel channel, Command command) {
    // 解析任务执行结果
    TaskResponseEvent responseEvent = JSONUtils.parseObject(command.getBody(), TaskResponseEvent.class);
    
    // 更新任务实例状态
    int taskInstanceId = responseEvent.getTaskInstanceId();
    ExecutionStatus status = responseEvent.getState();
    
    // 通知流程实例线程任务已完成
    WorkflowExecuteThread workflowThread = processInstanceExecMaps.get(responseEvent.getProcessInstanceId());
    workflowThread.handleTaskComplete(taskInstanceId, status, responseEvent.getVarPool());
}

五、全链路流程图

下面是任务从提交到执行的完整流程图:

mermaid

六、总结与最佳实践

6.1 任务提交流程关键点

  1. 状态持久化:流程实例和任务的状态会实时写入数据库,确保系统故障后可以恢复
  2. 异步处理:从命令创建到任务执行,整个流程采用异步处理,提高系统吞吐量
  3. 可扩展性:Master和Worker均可水平扩展,通过注册中心自动发现和负载均衡
  4. 容错机制:Master和Worker均有故障检测和自动恢复机制

6.2 常见问题排查

  1. 任务提交后无反应:检查API服务日志和数据库连接状态
  2. 任务卡在"等待运行"状态:检查Master服务是否正常运行,命令表是否有堆积
  3. 任务分配失败:检查Worker节点状态和网络连通性,查看Worker分组配置
  4. 任务执行失败:查看Worker节点日志和任务执行日志,通常位于logs/task目录

6.3 性能优化建议

  1. 根据任务类型合理配置Worker分组,避免资源竞争
  2. 调整Master的命令拉取间隔和Worker的心跳频率
  3. 对长时间运行的任务设置合理的超时时间
  4. 监控系统资源使用情况,及时扩容Master和Worker节点

通过了解DolphinScheduler的任务提交流程,不仅可以帮助用户更好地使用系统,还能为定制化开发和问题排查提供指导。在实际应用中,建议结合系统日志和监控指标,深入理解任务在各个阶段的状态变化,从而更好地优化工作流设计和系统配置。

【免费下载链接】dolphinscheduler Apache DolphinScheduler is the modern data orchestration platform. Agile to create high performance workflow with low-code 【免费下载链接】dolphinscheduler 项目地址: https://gitcode.com/gh_mirrors/dolp/dolphinscheduler

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值