2021-10-11---2021SC@SDUSC---DolphinScheduler(3)

2021SC@SDUSC
10-11
DolphinScheduler(3)

10-11—2021SC@SDUSC-----DolphinScheduler(3)-----ProcessDefinitionService


org.apache.dolphinscheduler.api.service.ProcessDefinitionService承担流程定义具体的CURD逻辑,调用各种mapper、dao。

如下

public Map<String, Object> createProcessDefinition(User loginUser, String projectName, String name,
                                                       String processDefinitionJson, String desc, String locations, String connects) throws JsonProcessingException {

        Map<String, Object> result = new HashMap<>(5);
        Project project = projectMapper.queryByName(projectName);
        // check project auth
        Map<String, Object> checkResult = projectService.checkProjectAndAuth(loginUser, project, projectName);
        Status resultStatus = (Status) checkResult.get(Constants.STATUS);
        if (resultStatus != Status.SUCCESS) {
            return checkResult;
        }

        ProcessDefinition processDefine = new ProcessDefinition();
        Date now = new Date();

        ProcessData processData = JSONUtils.parseObject(processDefinitionJson, ProcessData.class);
        Map<String, Object> checkProcessJson = checkProcessNodeList(processData, processDefinitionJson);
        if (checkProcessJson.get(Constants.STATUS) != Status.SUCCESS) {
            return checkProcessJson;
        }

        processDefine.setName(name);
        processDefine.setReleaseState(ReleaseState.OFFLINE);
        processDefine.setProjectId(project.getId());
        processDefine.setUserId(loginUser.getId());
        processDefine.setProcessDefinitionJson(processDefinitionJson);
        processDefine.setDescription(desc);
        processDefine.setLocations(locations);
        processDefine.setConnects(connects);
        processDefine.setTimeout(processData.getTimeout());
        processDefine.setTenantId(processData.getTenantId());

        //custom global params
        List<Property> globalParamsList = processData.getGlobalParams();
        if (globalParamsList != null && globalParamsList.size() > 0) {
            Set<Property> globalParamsSet = new HashSet<>(globalParamsList);
            globalParamsList = new ArrayList<>(globalParamsSet);
            processDefine.setGlobalParamList(globalParamsList);
        }
        processDefine.setCreateTime(now);
        processDefine.setUpdateTime(now);
        processDefine.setFlag(Flag.YES);
        processDefineMapper.insert(processDefine);
        putMsg(result, Status.SUCCESS);
        result.put("processDefinitionId",processDefine.getId());
        return result;
    }

具体分析:

研读上面代码我们知道createProcessDefinition大概有以下功能:

    校验当前用户是否拥有所属项目的权限
    校验流程定义JSON是否合法。例如是否有环
    构造ProcessDefinition对象插入数据库
    设置HTTP返回结果

因为这些都不是核心逻辑,都不再深入展开。

dolphinscheduler-api其他的功能都不在分析,
因为到此流程定义信息已经写入到了数据库,跟API模块已经没有关系了。
但要知道ProcessDefinition对象插入到了哪张表,
这样才知道如何查询、更新这个表的。这个表就是前后台逻辑交互的关键。
从ProcessDefinition可以看出,数据最终插入t_ds_process_definition表
@Data
@TableName("t_ds_process_definition")
public class ProcessDefinition

其实也可以不用关注具体插入到了哪张表,好像只需要关系哪个地方用ProcessDefinitionMapper查询了数据就行了。

但根据之前的概念定义,我们知道每个流程定义是需要靠“定时”周期性触发的,这样的话我们可以猜测,系统并不会直接用ProcessDefinitionMapper查询流程定义,而是会根据定时关联的ProcessDefinition来调起DAG。这一点在MasterSchedulerThread的分析中已经可以看出来了。

SchedulerController、SchedulerService

考虑到Controler逻辑比较清楚,因而此处将controller和service合并分析。

同样SchedulerController几乎没有逻辑,全都交给了SchedulerService层。这里只分析SchedulerService.insertSchedule,简单浏览代码后,可以发现它跟createProcessDefinition逻辑差不多:

1.检验当前用户是否拥有所属项目的权限
2.检验流程定义JSON是否合法。例如是否有环
3.构造Schedule对象插入数据库
  1. 设置HTTP返回结果

当然除了上面4点还查询、更新了ProcessDefinition,主要是将Schedule和ProcessDefinition进行关联。

MasterSchedulerThread

Package org.apache.dolphinscheduler.server.master.runner;
import ···
/* master schelduler thread */
public class MasterSchechdulerThread implements Runnable {
     
      /**logger of MasterSchechdulerThread*/
      private static final Logger logger = LoggerFactory.getLogger(MasterSchedulerThread.class);
      /** master exec service     */
      private final ExecutorService masterExecService;
      /**dolphinscheduler databases interface */
      private final ProcessDao processDao;
      /**zookeeper master client */
      private final ZKMasterClient zkMasterClient;
      /** master exec thead num*/
      private int masterExecThreadNum;
      /**Configuration of MasterSchedulerThead */
      private final Configuration conf;
      /** constructor of MasterSchedulerThead...*/
      public MasterSchedulerThead(ZKMasterClient zkClient,processDao  processDao ,Configuration conf,int masterExecThreadNum){...}
      /** run of MasterSchedulerThread*/
      @Override 
      public void run(){ ligang,2019/3/29 13:49·Initial module eschduler-server commit
          while(Stopper.isRunner()){...}
      }
}

以上是MasterSchedulerThread类的概览图。

MasterSchedulerThread实现Runnable接口,很明显主要的逻辑应该在run方法内,而且根据经验以及前面的分析可以知道,这个方法内是一个“死”循环,且为了避免CPU飙升,会休眠一小段时间。

下面我们逐步展开、分析MasterSchedulerThread类


/**run of MasterSchedulerThread*/

@Override 
public void run(){
   while (Stopper.isRunning()){
      //process instance
      ProcessInstance processInstance = null;
      
      InterProcessMutex mutex = null;
      try{
          if(OSUtills.checResource(conf,isMaster.true)){
              //create distributed lock
          String znodeLock =zkMaskterClient.getMasterLockerPath();
           
          mutex =new     InterProcessMutex(zkMasterClient.getActiveCount);
          mutex.acquire();
         
          ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor)masterExecService;
          int activeCount = poolExecutor.getActiveCount();
          //make sure to scan and delete commend table in one transaction
          Command commend =processDao.findOneCommend();
          if(commend !=null){...}
         } 
      }
      //acessing the commend table every SLEEP_TIME_MILLTS milliseconds 
      Thread.sleep(Constants.SLEEP_TIME_MILLIS);
      
     }Catch(Exception e){
    Logger.error(''master scheduler thread exception : ''  +e.getMessage(),e);
    }finally{
    
    }AbstractZKClient.releaseMutex(mutex);
   }
}

从上图简单分析,总结一下run的逻辑:

  1. 调用OSUtils.checkResource,检查当前资源(内存、CPU)。
    2.资源超出阈值,则休眠1秒进入下一次循环。
  2. 检查zookeeper是否连接成功
    4.获取一个InterProcessMutex锁(分布式的公平可重入互斥锁)。也就是只有一个master可以获取到这个锁
  3. 查询一个Command,不为null时进行后续逻辑。
    6.休眠1秒,进入下一次循环
  4. 进入下一次循环之前,释放InterProcessMutex锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗的仓鼠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

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

抵扣说明:

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

余额充值