airflow調度問題排查

問題描述

現在公司使用的airflow調度器很慢,每次clear一個task之後,這個task要過一段時間纔會被調度器調度到,這個時間大約需要15-30s。

使用的airflow版本較老:v1.7.1.3

排查

  1. 參數問題
    airflow.cfg這個文件裏面有很多的關於scheduler的參數,其中跟調度密切相關的有幾個:

    • max_threads :這個是調度dag的進程數量,最多有CPU個數的進程。
    • scheduler_heartbeat_sec :這個是調度的時間間隔,如果上一次調度時間小於這個值,則在這個週期裏面不會進行調度。
    • min_file_process_interval:這個是自動去更新dag操作的時間間隔,值爲-1代表永不自動更新。
    • run_duration:scheduler進程重啓時間,值爲-1代表永不重啓
    • refresh_dags_every:這個是我自己新加的參數,表示經過多少次調度之後重新載入所有的dag

    上面這些參數在jobs.py這個文件裏面都可以看到相關的使用,其中最後一個refresh_dags_every這個參數在老的版本里面是寫死在SchedulerJob類構造函數裏面的[__init__函數默認傳參],這裏新加的意思只是把配置寫在airflow.cfg配置文件裏面,方便之後更改。
    在老的版本里面,SchedulerJob類裏面的_excute函數即爲調度的主要函數,這個函數做了下面幾件事:

    • 控制相同pool的任務併發數量,
    • 重載所有的dags[這個跟refresh_dags_every相關]
    • 開進程去均分處理所有的dags,把可以執行的task加入到一個全局的隊列裏面[跟max_threads相關]

    所以,直接去修改max_thread這個參數是可以得到最直接的感受的,把這個參數調整成CPU的個數,可以獲得最大的調度進程的數量,每個進程均分的dags越少,整體時間越快。爲什麼是整體時間?
    在這裏插入圖片描述
    這一段代碼是把所有可執行的task加入到隊列裏面,外循環的條件是隻要有一個進程還存活的話,就進入循環,相當於主進程已經在這裏開始join子進程了,在等待所有的進程結束,所以這一段的時間取決於子進程裏面運行時間最長的進程運行的時間。

    當我把這個值從默認的2改到8之後,調度的時間已經從15-20s降低到了4-8s,但是沒有直接獲得我想要的4倍的提升,肯定還有其他的問題。

  2. 數據庫問題
    在這裏插入圖片描述
    這個函數是用來處理pool的併發的,裏面有一個查詢task state的語句,之前都很快,但是使用過一段時間之後會很慢,查看數據庫,數據庫包含了很多的歷史數據,並且state這一列也沒有索引,所以導致一個很簡單的查詢語句使用了1s的時間。這裏的解決辦法是把這一列加上索引,或者說可以讓數據庫裏面只保存近一年的數據即可。我這裏使用了加索引的辦法,現在的查詢已經下降到了0.003 s左右,提升了很多。

總結

這個是第一次對開源工具性能調優的嘗試,的確把調度時間優化了很多,現在的每次的調度時間只需要2-3s就可以完成了。

  1. 日誌很重要,從日誌裏面可以分析出很多東西。
  2. 數據庫的慢查詢需要一定的時間去發現。
  3. 官方文檔也很重要,從上面可以獲得一些啓示。
  4. stackoverflow上面也有很多的類似的問題,可以先在上面搜索。

分析過程

在這裏插入圖片描述

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