Airflowのwebserverと、読み込みに時間がかかるDAGの話

クリスマスも近いので、Airflowのwebserverの話をしましょう。

# 言いたいこと
* **読み込みに時間がかかる**DAGがあると
 * そのDAGが読み込めないかもよ
 * Airflowの管理画面にアクセス出来ないかもよ
* タスク数だけなら割と多くても大丈夫だよ
 * Componserのデフォルト設定でも、千程度はいける？
* 未来は明るいよ


# Airflowを構成するモジュール
今回の主役のwebserverは、Airflowのモジュールの一つです。
他のモジュールには、

* scheduler
 * DAG/Taskのスケジューリング・状態の管理
* worker
 * タスクインスタンスを実際に実行
* database
 * TaskInstance・DagRun・xcom・Variableなどの保持
* executor
 * スケジュールされたタスクをworkerに配分

などがあります。
詳しくは、[Astronomerさんの記事](https://www.astronomer.io/guides/airflow-components/)がわかりやすいです。

# webserverとは

webserverは、管理画面（下図）・[CLIコマンド（の一部）](https://airflow.apache.org/docs/stable/cli.html)・[API](https://airflow.apache.org/docs/stable/api.html)などを担当するモジュールで、

* DAG/task instanceなどの状況把握
* DAG/task instanceの再実行や、ステータスの変更

などの処理を受け付けます。

内部的には、Flask+Gunicornの構成となっており、画面からのエンドポイントは[ここらへん](https://github.com/apache/airflow/blob/1.10.2/airflow/www/views.py)に定義されています。

![Airflow UI](https://airflow.apache.org/docs/stable/_images/dags.png)
（図はAirflow[公式ページ](https://airflow.apache.org/docs/stable/ui.html)より）

# 読み込みに時間がかかるDAG問題
webserverは、リクエストを受け付けるだけではなく、**DAGファイルを定期的に読み込み**ます。

その結果、DAGファイルの**読み込みに**時間がかかると、

* 該当のDAGが読み込めない
* webserverへのアクセスが重くなる
* アクセスすら出来ない（エラーページ表示）

ことがあり、

* [Composerのトラブルシューティング](https://cloud.google.com/composer/docs/how-to/using/troubleshooting-dags?hl=ja#dag_load_import_timeout)
* [Astronomerのプラクティス](https://www.astronomer.io/guides/dag-best-practices/)

などでも注意喚起？されています。

## 読み込みに時間がかかる？
DAGの**読み込みに時間がかかる**のと、**DAGRunの実行に時間がかかる**のは、混同しそうですが別の話で、今回問題にしているのは前者です。

例を出すと、これは**読み込みに時間がかかる**DAGで、

```
    sleep(10000000)
    start = DummyOperator(task_id='start')

```

これは**DAGRunの実行に時間がかかる**DAGです。

```
        def hoge():
            sleep(1000000)
        slow_task = PythonOperator(
            task_id='query_' + str(i),
            python_callable=hoge,
        )

```

タスク数が多かったり、**タスクの外で**外部にアクセスしていると、読み込みが遅くなる可能性があります。


## webserverがDAGをパースする流れ
細かい流れが気になる人向けに：

1. webserver起動時に、定期的に（※）[子プロセス（gunicorn worker）を再起動]
(https://github.com/apache/airflow/blob/4a344f13d26ecbb627bb9968895b290bfd86e4da/airflow/cli/commands/webserver_command.py#L146)するように設定
1. エンドポイントのファイルのロード時に[DagBagオブジェクトが作られる]
(https://github.com/apache/airflow/blob/cb8b2a1dc64c3ea6ba445893c65c6c953dfb476a/airflow/www/views.py#L92)
1. DagBagオブジェクトが作られる中で、[DAGファイルがパースされる](https://github.com/apache/airflow/blob/cb8b2a1dc64c3ea6ba445893c65c6c953dfb476a/airflow/models.py#L321)

※ 具体的にはworker_refresh_interval秒

## タスク数との関係
Cloud Composer(Airflow 1.10.2)・BigQueryOperatorのみのDAGで試したところ：

* DAGあたりに1000タスクくらいでは、デフォルト設定でも表示が出来る
* DAGあたりに3000タスクくらいになると、デフォルト設定では表示ができなくなる
  * webserverが重くてもSchedulerやWorkerは動きます（Stackdriverで確認）
  * タイムアウト(worker_refresh_interval)を伸ばしたり、読み込みを非同期(async_dagbag_loader)にするといける

なお、 Graph ViewやTree Viewだけが重い時は、[default_dag_run_display_numberを変えるといいらしい](https://airflow.apache.org/docs/stable/faq.html)です。




# 明るい未来の話
この「読み込みに時間がかかるDAG」に関しては、改善がいくつか提案されています。

Cloud Composerでは、webserver上の[DAGの読み込みを非同期](https://cloud.google.com/composer/docs/how-to/accessing/airflow-web-interface#asynchronous-load)にするオプションが実装されており、Airflow1.10.4にも[移植されています](https://issues.apache.org/jira/browse/AIRFLOW-4924)。


まだドラフトですが、[AIP-24 DAG Persistence in DB using JSON for Airflow Webserver and (optional) Scheduler](https://cwiki.apache.org/confluence/display/AIRFLOW/AIP-24+DAG+Persistence+in+DB+using+JSON+for+Airflow+Webserver+and+%28optional%29+Scheduler?focusedCommentId=123898950)という提案は、より大幅な変更で、

* webserverでのDAGのパースはやめる
* schedulerがDAGをパースし、シリアライズ結果をDBに入れる
* webserverは、その結果を使う

オプションを提案しています。
（webserverが状態を持っているのが、そもそも良くないよね[という話もあるらしい](https://cwiki.apache.org/confluence/display/AIRFLOW/AIP-19+Making+the+webserver+stateless)）


# Cloud Compserのwebserver

Cloud Composerのwebserverに関してのメモです：

* [テナントプロジェクト（顧客管理外のプロジェクト）・CPU2コアのGAE Flexibleで動く](https://cloud.google.com/composer/docs/concepts/overview?hl=ja)
 * スペックは変えられない…
* GKEクラスタの方にwebserverを移すことが[出来る](https://cloud.google.com/composer/docs/how-to/managing/deploy-webserver?hl=ja)
 * Airflow設定変えてもダメなら、試す価値はあるかも

ちなみに、Astronomer.ioの方は[vCPU・メモリ](https://www.astronomer.io/docs/running-jobs-and-scaling/)のサイズを変えられます。