如何有效地使气流损伤定义由数据库驱动

时间:2019-05-02 19:56:24

标签: python airflow

背景

我有些dag从第三方api中提取数据。

我们需要提取的帐户可能会随着时间变化。为了确定要提取的帐户,我们可能需要查询数据库或发出HTTP请求,具体取决于过程。

在通风之前,我们只需要在python脚本的开头获取帐户列表即可。然后,我们将遍历帐户列表,并将每个帐户提取到文件或我们需要执行的任何操作。

但是现在,使用气流,在帐户级别定义任务并让气流处理重试功能,日期范围和并行执行等是很有意义的。

因此,我的dag可能看起来像这样:

Tree view of dag.  Each account gets its one task for data pull.

问题

由于每个帐户都是一个任务,因此每次dag解析都需要访问该帐户列表。但是由于dag文件经常被解析,因此您不必整天查询数据库或等待来自每台计算机的每一个dag解析的REST调用。这可能会占用大量资源,并且可能会花费金钱。

问题

是否有一种很好的方法将这种类型的配置信息缓存在本地文件中,理想情况下具有指定的生存时间?

想法

我想过几种不同的方法:

  1. 写入csv或pickle文件,并使用mtime过期。
    • 与此有关的问题是,如果两个进程试图同时使文件过期,我可能会遇到冲突。我不知道这种情况发生的可能性或后果如何,但可能没有什么可怕的。
  2. 为所有此类过程创建一个通用的sqlite数据库。应该在第一次访问变量时自动创建。每个配置变量在表中都有一行。使用last_modified_datetime列来告知何时到期。
    • 需要更详尽的代码和依赖项。
  3. 使用气流变量
    • 关于这一点的妙处是它使用现有的数据库,因此每个查询不会有$,并且网络滞后也很合理,但是仍然需要网络往返。
    • 具有在多节点设置中所有节点都相同的优点。
    • 确定何时到期可能会出现问题,因此可能会创建配置管理器dag来定期更新配置变量。
    • 但这会增加部署和开发过程的复杂性-必须填充变量以正确定义DAG-所有开发人员也需要在本地进行管理,而不是像在创建时那样读取缓存方法。
  4. Subdags?
    • 从未使用过它们,但我怀疑它们可以在这里使用。但是无论如何,社区似乎都不鼓励他们使用...

您解决了这个问题吗?您是否找到了一个好的解决方案?这些似乎都不是很好。

2 个答案:

答案 0 :(得分:1)

气流默认DAG解析间隔非常宽容:5分钟。但这对于大多数人来说还是很多,因此,如果您的部署与新DAG的到期时间不太接近,则可以合理地加以增加。

通常,我会说在每个DAG解析心跳中发出REST请求并不坏。同样,如今,调度过程已与解析过程分离,因此不会影响任务调度的速度。 Airflow会为您缓存DAG定义。

如果您仍然有理由将自己的缓存放在最重要的位置,我的建议是缓存在定义服务器上,而不是在Airflow端。例如,在REST端点上使用缓存头,并在需要时自己处理缓存失效。但这可能是一些过早的优化,所以我的建议是开始时不使用它,而仅在您衡量有说服力的证据时才实施它。

编辑:关于Web服务器和Worker

的确,Web服务器也将触发DAG解析,但不确定其频率如何。可能遵循guicorn worker刷新间隔(默认为30秒)。默认情况下,工作人员也会在每个任务开始时执行此操作,但是如果您激活酸洗DAG,可以将其保存。不确定这是否是个好主意,我听说这注定要被弃用。

您可以尝试做的另一件事是将其缓存在Airflow流程本身中,以记住发出昂贵请求的功能。 Python为此提供了一个内置的functools(lru_cache),并且与酸洗一起使用,比起其他选项可能已经足够而且非常容易。

答案 1 :(得分:1)

我有完全相同的情况。

具有多个帐户的API调用。最初创建了一个python脚本来迭代列表。

当我开始使用Airflow时,请考虑您打算做什么。尝试了您列出的2个替代方案。经过一些实验后,如果HTTP调用失败,则决定使用简单的try-except块在python中处理重试逻辑。原因是

  1. 一个要维护的脚本
  2. 较少的气流物体
  3. 使用一个脚本,可重启性更加容易。 (在Airflow中重新启动失败的工作并不容易(不需要双关语))

最后取决于您,那是我的经验。