dolphinScheduler1.3.3(海豚调度)worker卡死

前言

对于我这个问题,我在社区上提过issues: https://github.com/apache/dolphinscheduler/issues/6959

但是没有人回复和提供解决方案。然后我只能自己改源码,把问题就解决了。我把解决方案放到issues上。但是前段时间社区关闭了我的问题。所以我放到这里吧。

问题

我的海豚集群版本是1.3.3,我有两个master节点和很多workergroup,其中一个workergroup有一个worker节点。

出现现象是:

当我这个worker节点服务宕了。配置到这个节点运行的工作task会进行死循环。

所有的任务,包括其他workerGroup 都会等待这个死循环结束才能执行。

不断的重复执行 org/apache/dolphinscheduler/server/master/consumer/TaskPriorityQueueConsumer.java 下 run()方法。每个线程重复一次。

举例:

比如我一共1000个任务。A组和B组 workerGroup分配任务各 500个。

我的master线程是100(海豚默认).

分配的500个任务都提交到B workerGroup了。这时候B唯一的 worker宕机了

那么所有master线程都在不断的执行上面run方法,不断的提交到这个宕机的worker上。

直到把线程池中100个线程都用完,依然还在不断提交。

这样会导致没有多余线程去提交任务到 A workerGroupA。所有的任务卡死等待。

分析原因

我理解的是。master线程会读取mysql元数据。发现任务是run状态就会提交任务。但是worker宕机了又提交失败。没有一个线程去改mysql元数据和记录失败的。就会不断的查询,提交。。。

当100个线程都这么做的时候。就会卡住。 master不会把任务提交到worker上。因为worker宕机了。所以不返回任务状态。

master提交任务 -> worker宕机提交失败 -> 100个线程不断提交导致提交线程占满 -> 没有多余线程提交任务,所有任务卡住 -> 海豚卡死

 虽然任务状态是提交成功。但是任务实例没有显示。

改源码

我的处理方式是,来个计数判断。如果线程提交超过50次失败。则直接返回任务失败。

master提交任务 -> worker宕机提交失败 -> 开始计算提交次数 -> 线程提交失败50次直接返回任务失败 -> 线程继续执行下个任务提交

更改源码,org/apache/dolphinscheduler/server/master/runner/MasterTaskExecThread.java

我设置了个简单的判断。如果循环判断50次提交失败。就直接显示任务失败。

public Boolean waitTaskQuit(){
        // query new state
        taskInstance = processService.findTaskInstanceById(taskInstance.getId());
        logger.info("wait task: process id: {}, task id:{}, task name:{} complete",
                this.taskInstance.getProcessInstanceId(), this.taskInstance.getId(), this.taskInstance.getName());

        //==================================================================
        // 二开:设置一个master提交的次数。目的是当提交失败大于50的时候直接kill任务。
        Integer num = 0;
//        logger.info("taskInstance.getHost()=>>>>"+taskInstance.getHost());
        //==================================================================
        while (Stopper.isRunning()){

            //this.cancel = false
            //this.processInstance.getState() = RUNNING_EXEUTION
            logger.info(this.cancel+"==>>>>"+this.processInstance.getState());
            logger.info("==>>>>"+taskInstance.getState()+"---->"+taskInstance.getState().typeIsFinished());

            try {
                if(this.processInstance == null){
                    return true;
                }
                // task instance add queue , waiting worker to kill
                if(this.cancel || this.processInstance.getState() == ExecutionStatus.READY_STOP){
                    cancelTaskInstance();
                }
                if(processInstance.getState() == ExecutionStatus.READY_PAUSE){
                    pauseTask();
                }
                // task instance finished
                if (taskInstance.getState().typeIsFinished()){
                    // if task is final result , then remove taskInstance from cache
                    taskInstanceCacheManager.removeByTaskInstanceId(taskInstance.getId());
                    break;
                }

//==================================================================
                // 二开:判断次数大于等于50 & 状态是提交 则直接取消task任务。
                if (num>=50 && taskInstance.getState() == ExecutionStatus.SUBMITTED_SUCCESS){
                    cancelTaskInstance();
                    logger.error("任务提交节点已down,自动kill");
                }else {
                    num++;
                    logger.info("master提交任务失败次数: "+num);
                }
//==================================================================

                if (checkTaskTimeout()) {
                    logger.error("checkTaskTimeout");
                    this.checkTimeoutFlag = !alertTimeout();
                }
                // updateProcessInstance task instance
                taskInstance = processService.findTaskInstanceById(taskInstance.getId());
                processInstance = processService.findProcessInstanceById(processInstance.getId());
                Thread.sleep(Constants.SLEEP_TIME_MILLIS);
            } catch (Exception e) {
                logger.error("exception",e);
                if (processInstance != null) {
                    logger.error("wait task quit failed, instance id:{}, task id:{}",
                            processInstance.getId(), taskInstance.getId());
                }
            }
        }
        return true;
    }

经过测试,问题的确已经修复了。并且经历了公司双十二,集群发生了worker宕机情况也并未阻塞所有任务。

当然我这个方法是属于治标不治本。因为最终问题还是海豚读取ZK的时候。发现集群oom导致的worker服务假死,但该假死服务依然存在ZK列表中。无法识别到假死worker。所以还是会提交。

截止2022年2月18日,海豚更新了2.0.3,不确定是否修复了这个BUG。我准备之后更新公司海豚。海豚1.3.3的BUG嗷嗷多。建议安装最新版本。

截止2022年4月18日,海豚更新了2.0.5版本,目前公司测试环境我已经更新了这个版本,测试发现已修复这个BUG。建议更新新版本。升级步骤及问题解决传送门icon-default.png?t=M5H6https://blog.csdn.net/weixin_45681127/article/details/124177991?spm=1001.2014.3001.5502

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值