dolphinscheduler v2.0.1 master和worker执行流程分析(三)

目录

Master提交执行

master注册的processor

思考1:

思考2:

可能的PR福利:


Master提交执行

如图中start -> end, master提交执行大致就是从command开始,到提交到consumer结束。

MasterSchedulerService :

        1. 负责消费command,并将command转化为processInstance,保存或更新DB并删除command,此时processInstance状态被更新为running状态。

        2. 如果processInstance级别设置超时,添加到超时队列。

        3. 创建WorkflowExecuteThread线程并首次提交,以后该线程的触发执行完全由事件驱动,该线程有且仅对应一个processInstance。

WorkflowExecuteThread

        1. 构建task dag图,用于触发提交下游

        2. submitPostNode()方法,核心提交下游的方法,这里需要注意,在dag中,task是被上游触发提交的,而非自己检测上游判断自己是否达到提交条件,所以当依赖多个上游时,下游就有可能被重复提交。

                1)内存构建taskInstance,这里没有落表

                2)判断可提交task,会提交到 readyToSubmitTaskQueue 队列

                3)触发readyToSubmitTaskQueue的执行,真正提交task,这里会通过判断上游task的状态来决定该task是否具备提交条件

TaskProcessor :

        根据task的类型不同,抽象出来不同TaskProcessor处理器,用来管理task整个生命周期的所有操作,包括submit(),run(),kill()等,主要有两个操作

        1. 将taskInstance保存DB,此时页面才看到一个task记录,状态为submit success

        2. 构建TaskExecutionContext,再封装为TaskPriority,添加到taskPriorityQueue队列

        3. 提交成功,会将task添加到task超时队列,task重试队列(见思考2),并且会将taskId到TaskProcessor映射缓存到activeTaskProcessorMaps,标识为激活的task,这个很重要,后面会参与process状态判断,触发task的其他操作等。

        4. 从readyToSubmitTaskQueue移除task

TaskPriorityQueueConsumer

        本质是个轮询线程,不断扫描处理taskPriorityQueue队列的TaskPriority。

        1. 根据不同策略选择worker进行提交。这里需要注意,worker选择策略只是优先选择出一个worker,不代表只会往这个worker上提交,具体提交策略是当一个worker提交失败后:会记录worker黑名单,从所有相同group的其他worker中,利用迭代器.next选择下一个worker继续提交,默认每个worker间隔100ms重试3次。

        2. 收集提交失败的,放回队列

        优化点1:

        如果采用的LowerWeightHostManager,最好是同group的worker按负载排序,优先选低负载的worker。

        优化点2:已修复

        当worker没有资源时,频繁刷日志,这里高版本已经优化了,原理是提交失败后sleep。

        日志:fail to execute : %s due to no suitable worker, current task needs worker group %s to execute

        

master注册的processor

这里重点说TaskAckProcessor和TaskResponseProcessor,当task提交到worker后,task在worker的执行情况主要靠这两个processor来接受了。并且会触发操作DB,更新task。最终会响应worker DBcommand。如图中两条粗红线所示。

TaskAckProcessor

        当worker接收到到task后,会给master响应ack,TaskAckProcessor接受到会封装ack event添加到TaskResponseService

TaskResponseProcessor

        当worker执行完task后,会给master响应result,TaskResponseProcessor接受到会封装result event添加到TaskResponseService

TaskResponseService

        1. 如果是ack会更新task的worker host,state为running状态,log路径等,并响应给worker的DBTaskAckProcessor

        2. 如果是result会更新task的state(success或failed),endtime等,并响应给worker的DBTaskResponseProcessor

        3. 封装TASK_STATE_CHANGE的event,添加到process线程,等待事件驱动执行

思考1:

任务如何按照优先级执行?

查看TaskPriority实现的compareTo()方法,大致是按照优先process级别,再task级别的优先级执行。

并且taskPriorityQueue队列是整个master服务级别的,添加进去的task是不区分租户和任务类型的,所以,有需求的同学需要二开TaskPriorityQueueConsumer的接受队列。

    public int compareTo(TaskPriority other) {
        if (this.getProcessInstancePriority() > other.getProcessInstancePriority()) {
            return 1;
        }
        if (this.getProcessInstancePriority() < other.getProcessInstancePriority()) {
            return -1;
        }

        if (this.getProcessInstanceId() > other.getProcessInstanceId()) {
            return 1;
        }
        if (this.getProcessInstanceId() < other.getProcessInstanceId()) {
            return -1;
        }

        if (this.getTaskInstancePriority() > other.getTaskInstancePriority()) {
            return 1;
        }
        if (this.getTaskInstancePriority() < other.getTaskInstancePriority()) {
            return -1;
        }

        if (this.getTaskId() > other.getTaskId()) {
            return 1;
        }
        if (this.getTaskId() < other.getTaskId()) {
            return -1;
        }

        return this.getGroupName().compareTo(other.getGroupName());
    }

思考2:

task的retry是如何实现的?

首先理解下StateWheelExecuteThread: 一个轮询线程,不断的扫描重试队列,判断task是否满足重试(task重试条件是失败,到达重试时间且有重试次数),当达到重试条件,会用task生成一个TASK_STATE_CHANGE的event,并添加到对应process的WorkflowExecuteThread线程,之后就等待事件驱动执行

TaskProcessor中,任务A1首次保存DB并提交到taskPriorityQueue队列后,就把A1添加到重试队列。当A1触发重试,会把A1提交到readyToSubmitTaskQueue,一直到保存DB时,才会判断task进行重置属性处理生成新的task A2,提交成功后,又将A2添加到重试队列,往复如此。

核心逻辑如下代码,1.task是失败状态,2.将A1设置flag = no,3.生成新的task A2,前提是processInstance状态不是RESDY_STOP和READY_PAUSE

由于重试间隔,在特定情况下,kill时有一个bug,会在kill逻辑中讲。

public TaskInstance submitTaskInstanceToDB(TaskInstance taskInstance, ProcessInstance processInstance) {
        ExecutionStatus processInstanceState = processInstance.getState();
        // 1. 判断task为失败
        if (taskInstance.getState().typeIsFailure()) {
            if (taskInstance.isSubProcess()) {
                taskInstance.setRetryTimes(taskInstance.getRetryTimes() + 1);
            } else {
                if (processInstanceState != ExecutionStatus.READY_STOP
                        && processInstanceState != ExecutionStatus.READY_PAUSE) {
                    // 2. 将重试task置为不可用 no
                    taskInstance.setFlag(Flag.NO);
                    updateTaskInstance(taskInstance);
                    // crate new task instance
                    if (taskInstance.getState() != ExecutionStatus.NEED_FAULT_TOLERANCE) {
                        taskInstance.setRetryTimes(taskInstance.getRetryTimes() + 1);
                    }
                    // 3. 重置属性,生成新的task
                    // 重置task一些属性,其余属性不变
                    taskInstance.setSubmitTime(null);
                    taskInstance.setLogPath(null);
                    taskInstance.setExecutePath(null);
                    taskInstance.setStartTime(null);
                    taskInstance.setEndTime(null);
                    taskInstance.setFlag(Flag.YES);
                    taskInstance.setHost(null);
                    // 设置id为0,保证新生成一条记录
                    taskInstance.setId(0);
                }
            }
        }
    ......
}

可能的PR福利:

// master提交出去,收到响应,进行缓存
taskInstanceCacheManager.cacheTaskInstance(taskAckCommand);

 TaskAckProcessor和TaskResponseProcessor都会在TaskInstanceCacheManager缓存taskInstance,但是没有找到释放的地方。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值