run命令運行過程
讀取dag文件生成task依賴關係,然後生成封裝airflow run的command命令,通過celery發送到executor端,重新執行該airflow run命令。
scheduler命令運行過程:
調度器通過SchedulerJob類run方法執行整個流程,包括使用多進程處理DagDir,包括生成Dag,產生DagRun,每個DagRun下又生成多個TaskInstance,然後將任務通過Executor分發到執行節點運行。涉及到的方法有:SchedulerJob類create_dag_run創建DagRun,DagRun類verify_integrity生成TaskInstance,任務封裝爲command命令後發送到執行節點,執行節點通過airflow run命令執行該command,此時Job類型爲LocalTaskJob
數據庫表關係:
dag_run表通過execution_date和task_instance關聯
task_instance通過job_id和job表關聯
通過airflow run命令觀察整個流程
cli.py的run函數
關鍵語句dag = get_dag(args),根據dag_id獲取dag實例
進入get_dag函數,關鍵語句dagbag = DagBag(process_subdir(args.subdir))
進入DagBag類__init__函數,關鍵語句self.collect_dags(dag_folder)
進入collect_dags函數,關鍵語句self.process_file(dag_folder, only_if_updated=only_if_updated)
進入process_file函數,關鍵語句
m = imp.load_source(mod_name, filepath) //filepath:DagDir目錄下的一個Dag文件,假設爲test.py
通過該語句test.py會被導入,語句被執行。在語句被執行時,比如test.py中有操作爲:run_this_last = DummyOperator(task_id='run_this_last', dag=dag),在基類BaseOperator的__init__函數中存在語句self.dag = dag,進而調用dag的setter方法,DummyOperator的實例被添加到該dag實例中。
所有的dag被保存在一個字典中。
task = dag.get_task(task_id=args.task_id),所有task的實例已經被添加到dag實例的字典中
_run(args, dag, ti)
進入_run函數,我們查看else項針對遠程執行任務的分支。關鍵語句
executor = GetDefaultExecutor() //獲取executor的實例
executor.start()
executor.queue_task_instance(
ti,
mark_success=args.mark_success,
pickle_id=pickle_id,
ignore_all_deps=args.ignore_all_dependencies,
ignore_depends_on_past=args.ignore_depends_on_past,
ignore_task_deps=args.ignore_dependencies,
ignore_ti_state=args.force,
pool=args.pool)
executor.heartbeat() //將命令隊列中的命令拿出來調用executor的execute_async方法發送過去,然後同步等結果
executor.end()
進入queue_task_instance函數,此處是CeleryExcutor類的實例,基類BaseExecutor
command = task_instance.command(
local=True,
mark_success=mark_success,
ignore_all_deps=ignore_all_deps,
ignore_depends_on_past=ignore_depends_on_past,
ignore_task_deps=ignore_task_deps,
ignore_ti_state=ignore_ti_state,
pool=pool,
pickle_id=pickle_id,
cfg_path=cfg_path)
self.queue_command( //將command放入隊列
task_instance,
command,
priority=task_instance.task.priority_weight_total,
queue=task_instance.task.queue)
再次進入command函數,我們發現它依次調用了command_as_list、TaskInstance.generate_command
iso = execution_date.isoformat()
cmd = ["airflow", "run", str(dag_id), str(task_id), str(iso)]
cmd.extend(["--mark_success"]) if mark_success else None
cmd.extend(["--pickle", str(pickle_id)]) if pickle_id else None
cmd.extend(["--job_id", str(job_id)]) if job_id else None
cmd.extend(["-A"]) if ignore_all_deps else None
cmd.extend(["-i"]) if ignore_task_deps else None
cmd.extend(["-I"]) if ignore_depends_on_past else None
cmd.extend(["--force"]) if ignore_ti_state else None
cmd.extend(["--local"]) if local else None
cmd.extend(["--pool", pool]) if pool else None
cmd.extend(["--raw"]) if raw else None
cmd.extend(["-sd", file_path]) if file_path else None
cmd.extend(["--cfg_path", cfg_path]) if cfg_path else None
return cmd
結果就是:服務端發送一個airflow run命令到executor,然後通過Celery執行shell命令,命令內容就是上面的cmd結果。然後executor端會重新執行一遍airflow run命令。
整個流程結束