airflow整體架構

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命令。
整個流程結束

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章