Airflow Deferrable Operators

文章目录

依赖

  1. Python3.7以上,需要使用asyncio这个库。
  2. airflow 版本需要在2.2以上。
  3. 需要启动triggerer这个airflow进程。

使用

新加自己的DeferrableOperators,一般要经过三步:

  1. 还是继承原来的BaseSensorOperator。
from airflow.sensors.base import BaseSensorOperator
class ExecutionDateTimeSensorAsync(BaseSensorOperator):
    def __init__(self, *, target_time, **kwargs):
        super().__init__(**kwargs)
        self.daily_target_time = target_time

    def init_real_execution_datetime(self, context):
        time_list = self.daily_target_time.split(':')
        if len(time_list) != 2:
            raise
        hour = int(time_list[0])
        minute = int(time_list[1])
        utc_target_datetime = datetime.strptime(self.daily_target_time, "%H:%M")
        china_target_datetime = utc_target_datetime.replace(tzinfo=dateutil.tz.gettz('Asia/Shanghai'))

        execution_date_str = (context['execution_date'] + timedelta(days=1)).strftime("%Y-%m-%d")
        real_date_str = execution_date_str + ' ' + self.daily_target_time
        real_execution_datetime = datetime.strptime(real_date_str, "%Y-%m-%d %H:%M")

    def execute(self, context):
        self.init_real_execution_datetime(context)
        self.defer(
            trigger=ExecutionDateTimeTrigger(moment=self.real_execution_datetime),
            method_name="execute_complate"
        )
    def execute_complete(self, context, event=None):
        # 可以做一些额外的工作,发邮件、告警之类,return之后就会把这个Sensor Mark Success了。
        return
  1. 新加一个自己的Trigger
    最恶心人的地方是加Trigger,需要把新加的trigger放到一个系统路径下,serialize这个函数返回的元组的第一个参数必须填写这个路径,trigger这个进程才能找到trigger的定义去实例化这个trigger。
from airflow.triggers.base import BaseTrigger, TriggerEvent
import pytz
utc = pytz.UTC

class ExecutionTimeTrigger(BaseTrigger):
    def __init__(self, moment):
        super().__init__()
        self.moment = moment.replace(tzinfo=utc)
    
    def serialize(self):
        return ("airflow.triggers.temporal.ExecutionTimeTrigger", {"moment": self.moment})
    
    async def run(self):
        self.log.info('--- {} ---'.format(self.moment))
        while (self.moment > datetime.datetime.now().replace(tzinfo=utc)):
            await asyncio.sleep(1)
        yield TriggerEvent(self.moment)
  1. airflow启动triggerer这个进程
airflow triggerer

效果

如果使用原生的TimeSensor之类的Sensor,如果这个TimeSensor前置任务已经好了的话,状态马上就会被置成SCHEDULEABLE并且被executor弄成RUNNING状态,占用worker进程资源。

在使用原生的Sensor,并行150个任务的时候,会占用13G左右的内存,并且消耗CPU在无意义的轮询中。

使用Deferrable Operators和Trigger之后,Triggerer这个进程会帮我们做掉这种无意义的轮询。当Trigger里面的run函数真正yield的时候就是这个trigger完成的时候,会把这个任务置成Success状态,跟普通的Sensor行为一致。之后所有的这种时间等待、文件等待任务都可以使用新的Deferrable Operators来完成,但是需要写新的Trigger逻辑。

用新的Deferrable Operators之后,额外使用的内存只有0.2G左右。节省了很多worker、内存、cpu资源。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值