Netflix conductor 工作流及任务定义

1. 交互流程

  • 用户定义task Definition:Worker通过自己的name和task的name比对,确认是否处理此任务。
  • 用户定义workflow,引用之前定义的taskDefinition。此时用户需要定义task的入参和出参。
  • 用户启动worker,等待执行任务。
  • 用户执行workflow。需要定义workflow的入参和出参。
  • workflow执行完成,用户可查看执行结果。

 

2. 定义input output

conductor的task分为两种:系统定义task和用户定义task。

系统定义task是为了完成工作流的组织和流转。

用户定义task 是为了完成用户定义的功能。

工作流中的task,必须要先定义。

task definition中定义task支持哪些输入和输出的名字:inputKeys,outputKeys。

工作流中引用task的时候,定义task的入参inputParameters。

工作流定义的时候,可以指定工作流的输入inputParameters和输出outputParameters。如果没有指定输出,则默认采用最后一个任务的输出,作为整体工作流的输出。

 

conductor的出参和入参定义非常灵活。task的inputparameters是一个json字段。其中的值可以包含来自workflow入参的引用以及其他task运行结果的引用。

引用的格式:${SOURCE.input/output.JSONPath}

 

SOURCE

可以为"workflow"或者其他task的referenceName

input/output

SOURCE字段的输入或输出

JSONPath

json路径。

下面是官网给出的实例。其中包括了怎样从工作流引用入参,从task引用出参,以及定义固定值。

{
    "inputParameters": {
        "movieId": "${workflow.input.movieId}",
        "url": "${workflow.input.fileLocation}",
        "lang": "${loc_task.output.languages[0]}",
        "http_request": {
            "method": "POST",
            "url": "http://example.com/${loc_task.output.fileId}/encode",
            "body": {
                "recipe": "${workflow.input.recipe}",
                "params": {
                    "width": 100,
                    "height": 100
                }
            },
            "headers": {
                "Accept": "application/json",
                "Content-Type": "application/json"
            }
        }
    }
}

 

3. 代码实现分析

当有任务执行结束后,会调用server的updateTask rest接口。server会根据workflow的流程,再次发布需要执行的task。task的入参会被填充。ParametersUtil负责解析和填充参数。

Netflix conductor 工作流及任务定义_第1张图片

下面是server填充参数的代码。conductor提取了workflow的输入和输出,以及workflow的一些其他属性值。conductor还提取了workflow所有任务的输入输出以及任务的属性值。所以在task定义中,我们可以引用下面所有的属性。

public Map getTaskInputV2(Map input, Workflow workflow, String taskId, TaskDef taskDef) {

             ......

             

             Map wf = new HashMap<>();
             wf.put("input", workflow.getInput());
             wf.put("output", workflow.getOutput());
             wf.put("status", workflow.getStatus());
             wf.put("workflowId", workflow.getWorkflowId());
             wf.put("parentWorkflowId", workflow.getParentWorkflowId());
             wf.put("parentWorkflowTaskId", workflow.getParentWorkflowTaskId());
             wf.put("workflowType", workflow.getWorkflowType());
             wf.put("version", workflow.getVersion());
             wf.put("correlationId", workflow.getCorrelationId());
             wf.put("reasonForIncompletion", workflow.getReasonForIncompletion());
             wf.put("schemaVersion", workflow.getSchemaVersion());
             

             inputMap.put("workflow", wf);
             
              workflow.getTasks().stream().map(Task::getReferenceTaskName).map(taskRefName -> workflow.getTaskByRefName(taskRefName)).forEach(task -> {
                    Map taskIO = new HashMap<>();
                    taskIO.put("input", task.getInputData());
                    taskIO.put("output", task.getOutputData());
                    taskIO.put("taskType", task.getTaskType());
                    if(task.getStatus() != null) {
                           taskIO.put("status", task.getStatus().toString());
                    }
                    taskIO.put("referenceTaskName", task.getReferenceTaskName());
                    taskIO.put("retryCount", task.getRetryCount());
                    taskIO.put("correlationId", task.getCorrelationId());
                    taskIO.put("pollCount", task.getPollCount());
                    taskIO.put("taskDefName", task.getTaskDefName());
                    taskIO.put("scheduledTime", task.getScheduledTime());
                    taskIO.put("startTime", task.getStartTime());
                    taskIO.put("endTime", task.getEndTime());
                    taskIO.put("workflowInstanceId", task.getWorkflowInstanceId());
                    taskIO.put("taskId", task.getTaskId());
                    taskIO.put("reasonForIncompletion", task.getReasonForIncompletion());
                    taskIO.put("callbackAfterSeconds", task.getCallbackAfterSeconds());
                    taskIO.put("workerId", task.getWorkerId());
                    inputMap.put(task.getReferenceTaskName(), taskIO);
             });
             Configuration option = Configuration.defaultConfiguration().addOptions(Option.SUPPRESS_EXCEPTIONS);
             DocumentContext io = JsonPath.parse(inputMap, option);
             Map replaced = replace(inputParams, io, taskId);
             return replaced;

       }
  1. 总结

conductor提供了json的入参格式,可以定义复杂的入参。

conductor提供了task之间,以及workflow和task之间的参数引用。

conductor的task可以引用其他task的入参出参,但是没有根据参数引用强制task的执行顺序。task的执行还是按照工作流的定义进行。

转载于:https://my.oschina.net/u/347227/blog/1499635

你可能感兴趣的:(Netflix conductor 工作流及任务定义)