Slide 1

Slide 1 text

Deferrable Operators入門 Hank Ehly

Slide 2

Slide 2 text

よろしくお願いします Hank Ehly(名:ハンク 姓:イーリー) アメリカ、カンザス州出身 ENECHANGE株式会社 (エンジニア) ● qiita.com/hankehly ● github.com/hankehly ● linkedin.com/in/hankehly ● twitter.com/hankehly ● connpass.com/user/hankehly

Slide 3

Slide 3 text

OperatorsとSensorsの復習 ● Operatorは、アクションを起こす ● Sensorは、指定の条件が満たされるまで待つ ● 1 worker_slot が必要 ○ Taskの最大同時実行数 = worker_slotの数 ○ Poolレコードとして管理される ○ default_pool: 128 slot

Slide 4

Slide 4 text

問題例 x128 実行中 実行待ち Airflowタスク キュー Sensorの 待機処理 レポート作成 Sparkジョブ POINT 重要なタスクがあるのに「待機処理」で忙 しくて worker_slot が足りない 実行完了

Slide 5

Slide 5 text

Sensorのpokeとrescheduleモード worker_slotを確保したまま、待ち続ける 00:00 01:00 02:00 03:00 04:00 pokeモード worker_slot確保時間 rescheduleモード 00:00 01:00 02:00 03:00 04:00 指定条件が満たされない場合、 worker_slotを解放して タスクを再スケジューリングする

Slide 6

Slide 6 text

● 2.2.0+ (2021年10月〜) ● worker_slot を使わずに、待機処理できるOperator/Sensor ● 処理を中断(英:defer)し、Trigger に待機処理を任せる ● Triggerは実行中、worker_slotを使わない ○ 別途「triggerer」プロセスが実行してくれる ○ worker_slot の節約ができる Deferrable Operatorsとは

Slide 7

Slide 7 text

待機処理で worker_slot を使わなくて済む ● Performance: タスク開始〜終了までの時間(ターンアラウンドタイム)短縮 ● Cost(¥): Workerを減らせるから、お金が節約できる Deferrable Operatorsの利点

Slide 8

Slide 8 text

実践編

Slide 9

Slide 9 text

Deferrable Operatorsの処理の流れ Sparkジョブの終了を待つ (2時間) 結果のURLをXcom にPushする Sparkジョブを 開始する (worker_slot 確保中) 実行開始 ① self.defer(trigger) ② (worker_slot 確保中) タスクを再開する ④ Trigger実行 ③ (triggerer プロセス)

Slide 10

Slide 10 text

Deferrable Operatorsの使い方 (Triggererプロセス) Web Server Worker Scheduler Triggerer (数を増やせば可用性が高まる) services: airflow-triggerer: <<: *airflow-common command: triggerer healthcheck: test: ["CMD-SHELL", 'airflow jobs check --job-type TriggererJob --hostname "$${HOSTNAME}"'] interval: 10s timeout: 10s retries: 5 restart: always depends_on: <<: *airflow-common-depends-on airflow-init: condition: service_completed_successfully 公式 docker-compose.yaml : https://airflow.apache.org/docs/apache-airflow/2.5.2/docker-compose.yaml

Slide 11

Slide 11 text

Deferrable Operatorsの使い方 (Triggererプロセス) $ airflow webserver|scheduler|worker|triggerer

Slide 12

Slide 12 text

Deferrable Operatorsの使い方 (DAG実装) from airflow.decorators import dag from airflow.providers.google.cloud.operators.bigquery import BigQueryInsertJobOperator @dag(...) def example_dag(): load_data = BigQueryInsertJobOperator( task_id="load_data", configuration={ "load": { "sourceUris": ["gs://my-bucket/my-5TB-dataset/*.parquet"], "destinationTable": "my_dataset.my_table" } } ) worker_slot を ずっと確保したまま

Slide 13

Slide 13 text

from airflow.decorators import dag -from airflow.providers.google.cloud.operators.bigquery import BigQueryInsertJobOperator   +from astronomer.providers.google.cloud.operators.bigquery import (   + BigQueryInsertJobOperatorAsync as BigQueryInsertJobOperator   +)   @dag(...) def example_dag(): load_data = BigQueryInsertJobOperator( task_id="load_data", configuration={ "load": { "sourceUris": ["gs://my-bucket/my-5TB-dataset/*.parquet"], "destinationTable": "my_dataset.my_table" } } ) Deferrable Operatorsの使い方 (DAG実装) クラスの差し替えだけ (pip install astronomer-providers)

Slide 14

Slide 14 text

Deferrable Operatorsの書き方 from datetime import timedelta from airflow.sensors.base import BaseSensorOperator from airflow.triggers.temporal import TimeDeltaTrigger class WaitOneHourSensor(BaseSensorOperator): def execute(self, context): self.defer(trigger=TimeDeltaTrigger(timedelta(hours=1)), method_name="execute_complete") def execute_complete(self, context, event=None): # We have no more work to do here. Mark as complete. return 処理を中断する Triggerオブジェクトを渡す (待機処理を行う) どこから再開するか Triggerの実行結果

Slide 15

Slide 15 text

Triggerの書き方 import asyncio from airflow.triggers.base import BaseTrigger, TriggerEvent from airflow.utils import timezone class DateTimeTrigger(BaseTrigger): def __init__(self, moment): super().__init__() self.moment = moment def serialize(self): return ("airflow.triggers.temporal.DateTimeTrigger", {"moment": self.moment}) async def run(self): while self.moment > timezone.utcnow(): await asyncio.sleep(1) yield TriggerEvent(self.moment) 一致するように書く 待機処理後に TriggerEvent を yield して 元のタスクを再開する 待機処理 triggerer 側で再インスタンス化 するための情報 asyncioで実装

Slide 16

Slide 16 text

まとめ ● Deferrable Operators で Worker リソースの節約ができる(時間/円) ● Trigger は、Operatorの代わりに「待機処理」をしてくれる ● Trigger は、triggerer プロセスが実行する(worker_slot不要) x128 実行中 実行待ち (詰まっている) ● 待機処理が多いDAGにおすすめ たくさんのSensorタスク

Slide 17

Slide 17 text

ご清聴ありがとうございます ドキュメント ● Deferrable Operators & Triggers — Airflow Documentation ● Deferrable operators | Astronomer Documentation Youtube ● Airflow: Save Tons of Money by Using Deferrable Operators - Kaxil Naik, Astronomer ● Love for writing deferrable operators Why and how to defer ● All About Deferrables