《基于Apache Airflow的数据流管道》第二章:Airflow DAG 解剖

本章涵盖内容:

  • 在您自己的机器上运行Airflow
  • 编写并运行您的第一个工作流
  • 查看Airflow界面的第一个视图
  • 处理Airflow中的任务失败

在前一章中,我们了解了为什么在处理数据及其众多工具时并不容易。在本章中,我们将开始学习Airflow,并查看一个使用许多工作流中常见基本构建块的示例工作流。

在开始使用Airflow时,具有一些Python经验会有所帮助,因为工作流是用Python代码定义的。但学习Airflow的基础并不那么困难。一般来说,快速建立一个Airflow工作流的基本结构是容易的。让我们深入了解一个火箭爱好者的用例,看看Airflow如何帮助他。

收集来自众多来源的数据

火箭是人类工程学的奇迹之一,每次火箭发射都吸引了全世界的关注。在本章中,我们介绍一个火箭爱好者约翰的故事,他追踪和关注每一次火箭发射。关于火箭发射的新闻来自许多约翰关注的新闻来源,理想情况下,约翰希望将所有火箭新闻汇总到一个地方。约翰最近开始学习编程,并希望有一种自动化的方式来收集所有火箭发射的信息,并最终获得有关最新火箭新闻的一些个人见解。为了从小处着手,约翰决定首先收集火箭的图片。

探索数据

对于数据,我们使用Launch Library 2(thespacedevs.com/llapi),这是一个在线的数据仓库,包含来自各种来源的历史和未来火箭发射的数据。它是一个免费且开放的API,供地球上的任何人使用(受速率限制影响)。

约翰目前只对即将发射的火箭感兴趣。幸运的是,Launch Library正好提供了他正在寻找的数据(ll.thespacedevs.com/2.0.0/launc...)。它提供了即将发射的火箭发射的数据,以及相应火箭图片的URL。以下是此URL返回的部分数据片段。

json 复制代码
$ curl -L "https://ll.thespacedevs.com/2.0.0/launch/upcoming"               ❶
 
{                                                                           ❷
 ...
 "results": [                                                               ❸
   {                                                                        ❹
     "id": "528b72ff-e47e-46a3-b7ad-23b2ffcec2f2",
     "url": "https://.../528b72ff-e47e-46a3-b7ad-23b2ffcec2f2/",
     "launch_library_id": 2103,                                             ❺
     "name": "Falcon 9 Block 5 | NROL-108",                                 ❺
     "net": "2020-12-19T14:00:00Z",                                         ❺
     "window_end": "2020-12-19T17:00:00Z",                                  ❺
     "window_start": "2020-12-19T14:00:00Z",                                ❺
     ➥ "image":
     "https://spacelaunchnow-prod-east.nyc3.digitaloceanspaces.com/
      media/launch_images/falcon2520925_image_20201217060406.jpeg",         ❻
     "infographic": ".../falcon2520925_infographic_20201217162942.png",
     ...
   },
   {
     "id": "57c418cc-97ae-4d8e-b806-bb0e0345217f",
     "url": "https://.../57c418cc-97ae-4d8e-b806-bb0e0345217f/",
     "launch_library_id": null,
     "name": "Long March 8  | XJY-7 & others",
     "net": "2020-12-22T04:29:00Z",
     "window_end": "2020-12-22T05:03:00Z",
     "window_start": "2020-12-22T04:29:00Z",
     "image": "https://.../long2520march_image_20201216110501.jpeg",
     "infographic": null,
     ...
   },
   ...
 ]
}

❶ 从命令行使用curl检查URL的响应。

❷ 响应是一个JSON文档,您可以通过其结构看到。

❸ 方括号表示一个列表。

❹ 所有花括号内的值都是指一个单独的火箭发射。

❺ 在这里,我们看到了火箭ID以及火箭发射窗口的开始和结束时间。

❻ 一个指向发射火箭图片的URL。

正如您所看到的,数据以JSON格式提供了火箭发射的信息,对于每次发射,都有关于特定火箭的信息,比如ID、名称和图片URL。这正是约翰所需的内容,他最初绘制了图2.1中的计划,以收集即将发射的火箭图片(例如,将屏幕保护程序指向保存这些图片的目录):

根据图2.1中的示例,我们可以看出,归根结底,约翰的目标是拥有一个充满火箭图片的目录,例如图2.2中的阿丽亚娜5 ECA火箭的图片。

编写您的第一个Airflow DAG(有向无环图)

约翰的用例范围很好,让我们看看如何编写他的计划。这只需要几个步骤,在理论上,通过一些Bash技巧,您可以在一行命令中完成它。那么为什么我们需要像Airflow这样的系统来完成这项工作呢?

Airflow的好处在于,我们可以将一个由一个或多个步骤组成的大型作业拆分为单独的"任务",这些任务共同形成一个DAG(有向无环图)。多个任务可以并行运行,并且任务可以运行不同的技术。例如,我们可以先运行一个Bash脚本,然后再运行一个Python脚本。在图2.3中,我们将约翰关于工作流程的心智模型分解为Airflow中的三个逻辑任务。

您可能会问,为什么选择这三个任务?为什么不在一个单独的任务中下载发射和相应的图片呢?或者为什么不将它们拆分为五个任务?毕竟,在约翰的计划中有五个箭头。这些都是在开发工作流时需要考虑的有效问题,但事实上,并没有正确或错误的答案。然而,有几个要考虑的因素,在本书中,我们将解决许多这样的用例,以了解什么是正确的,什么是错误的。该工作流的代码如下。

ini 复制代码
import json
import pathlib
 
import airflow
import requests
import requests.exceptions as requests_exceptions
from airflow import DAG
from airflow.operators.bash import BashOperator
from airflow.operators.python import PythonOperator
 
dag = DAG(                                                     ❶
   dag_id="download_rocket_launches",                          ❷
   start_date=airflow.utils.dates.days_ago(14),                ❸
   schedule_interval=None,                                     ❹
)
 
download_launches = BashOperator(                              ❺
   task_id="download_launches",                                ❻
   bash_command="curl -o /tmp/launches.json -L 'https://ll.thespacedevs.com/2.0.0/launch/upcoming'",
   dag=dag,
)
 
 
def _get_pictures():                                           ❼
   # Ensure directory exists
   pathlib.Path("/tmp/images").mkdir(parents=True, exist_ok=True)
 
   # Download all pictures in launches.json
   with open("/tmp/launches.json") as f:
       launches = json.load(f)
       image_urls = [launch["image"] for launch in launches["results"]]
       for image_url in image_urls:
           try:
               response = requests.get(image_url)
               image_filename = image_url.split("/")[-1]
               target_file = f"/tmp/images/{image_filename}"
               with open(target_file, "wb") as f:
                   f.write(response.content)
               print(f"Downloaded {image_url} to {target_file}")
           except requests_exceptions.MissingSchema:
               print(f"{image_url} appears to be an invalid URL.")
           except requests_exceptions.ConnectionError:
               print(f"Could not connect to {image_url}.")
 
 
get_pictures = PythonOperator(                                ❽
   task_id="get_pictures",
   python_callable=_get_pictures,                             ❽
   dag=dag,
)
 
notify = BashOperator(
   task_id="notify",
   bash_command='echo "There are now $(ls /tmp/images/ | wc -l) images."',
   dag=dag,
)
 
download_launches >> get_pictures >> notify                   ❾

❶ 实例化一个DAG对象;这是任何工作流的起点。

❷ DAG的名称

❸ DAG应该首次开始运行的日期

❹ DAG应该运行的间隔

❺ 使用Bash来使用curl下载URL的响应。

❻ 任务的名称

❼ 一个Python函数将解析响应并下载所有火箭图片。

❽ 在DAG中使用PythonOperator调用Python函数。

❾ 设置任务的执行顺序。

让我们分解这个工作流程。DAG是任何工作流程的起点。工作流程中的所有任务都引用这个DAG对象,这样Airflow就知道哪些任务属于哪个DAG。

ini 复制代码
dag = DAG(                                          ❶
   dag_id="download_rocket_launches",               ❷
   start_date=airflow.utils.dates.days_ago(14),     ❸
   schedule_interval=None,
)

❶ DAG类需要两个必需的参数。

❷ 在Airflow用户界面(UI)中显示的DAG名称

❸ 工作流程首次运行的日期时间

请注意,(小写的)dag是分配给(大写的)DAG类实例的名称。实例的名称可以是任意的;您可以将其命名为rocket_dag或任何您喜欢的名称。我们将在所有操作器中引用该变量(小写的dag),这告诉Airflow该操作器属于哪个DAG。

同时请注意,我们将schedule_interval设置为None。这意味着DAG不会自动运行。目前,您可以在Airflow UI中手动触发它。我们将在第2.4节讨论调度。

接下来,Airflow的工作流脚本由一个或多个操作器组成,这些操作器执行实际的工作。在2.4节的代码清单中,我们使用BashOperator来运行Bash命令。

ini 复制代码
download_launches = BashOperator(
   task_id="download_launches",                           ❶
   bash_command="curl -o /tmp/launches.json 'https://     ❷
ll.thespacedevs.com/2.0.0/launch/upcoming'",              ❷
   dag=dag,                                               ❸
)

❶ 任务的名称

❷ 要执行的Bash命令

❸ 对DAG变量的引用

每个操作器执行一个单独的工作单元,多个操作器共同形成Airflow中的工作流或DAG。操作器彼此独立运行,尽管您可以定义执行顺序,我们在Airflow中称之为依赖关系。毕竟,如果您在没有关于图片位置的数据的情况下尝试首先下载图片,约翰的工作流将是没有用的。为了确保任务按正确的顺序运行,我们可以在任务之间设置依赖关系。

download_launches >> get_pictures >> notify        ❶

❶ 箭头设置任务的执行顺序

在Airflow中,我们可以使用二进制右移运算符(即"rshift" [>>])来定义任务之间的依赖关系。这确保get_pictures任务仅在download_launches成功完成后运行,而notify任务仅在get_pictures成功完成后运行。

注意:在Python中,右移运算符(>>)用于对位进行移位操作,这是例如密码学库中常见的操作。在Airflow中,没有位移的用例,而rshift运算符被重写为提供一种可读的方式来定义任务之间的依赖关系。

任务 vs 操作器

您可能会想知道任务(task)和操作器(operator)之间的区别是什么。毕竟,它们都执行一小段代码。在Airflow中,操作器有一个单一的责任:它们存在于执行一个单一的工作任务。一些操作器执行通用的工作,比如BashOperator(用于运行Bash脚本)或PythonOperator(用于运行Python函数);其他操作器有更具体的用例,比如EmailOperator(用于发送电子邮件)或SimpleHTTPOperator(用于调用HTTP端点)。无论哪种方式,它们都执行单一的工作。

DAG的角色是编排一组操作器的执行。这包括启动和停止操作器,当一个操作器完成后启动连续的任务,确保操作器之间的依赖关系得到满足等等。

在这种情况下,在整个Airflow文档中,我们看到操作器和任务这两个术语可以互换使用。从用户的角度来看,它们指的是同一件事情,在讨论中这两个术语经常相互替代。操作器提供了执行一项工作的实现。Airflow有一个名为BaseOperator的类和许多继承自BaseOperator的子类,比如PythonOperator、EmailOperator和OracleOperator。

然而,它们之间还是有区别的。Airflow中的任务(task)管理操作器的执行;可以将它们视为围绕操作器的一个小包装或管理器,确保操作器正确执行。用户可以通过使用操作器专注于要完成的工作,而Airflow通过任务确保工作的正确执行(见图2.4)。

运行任意的Python代码

获取下一次火箭发射的数据可以通过一个Bash中的单个curl命令来完成,这很容易通过BashOperator执行。然而,解析JSON结果,从中选择图片URL,并下载相应的图片需要更多的工作。虽然所有这些在Bash中仍然可以用一行命令完成,但使用几行Python或您选择的其他语言通常更容易和更易读。由于Airflow代码是用Python定义的,因此将工作流程和执行逻辑都放在同一个脚本中非常方便。为了下载火箭图片,我们实现了清单2.6的代码。

python 复制代码
def _get_pictures():                                                    ❶
   # Ensure directory exists
   pathlib.Path("/tmp/images").mkdir(parents=True, exist_ok=True)       ❷
 
   # Download all pictures in launches.json
   with open("/tmp/launches.json") as f:                                ❸
       launches = json.load(f)
       image_urls = [launch["image"] for launch in launches["results"]]
       for image_url in image_urls:
           try:
               response = requests.get(image_url)                       ❹
               image_filename = image_url.split("/")[-1]
               target_file = f"/tmp/images/{image_filename}"
               with open(target_file, "wb") as f:
                   f.write(response.content)                            ❺
               print(f"Downloaded {image_url} to {target_file}")        ❻
           except requests_exceptions.MissingSchema:
               print(f"{image_url} appears to be an invalid URL.")
           except requests_exceptions.ConnectionError:
               print(f"Could not connect to {image_url}.")
 
 
get_pictures = PythonOperator(                                          ❼
   task_id="get_pictures",
   python_callable=_get_pictures,                                       ❽
   dag=dag,
)

❶ 调用的Python函数

❷ 如果目录不存在,则创建图片目录。

❸ 打开上一个任务的结果。

❹ 下载每个图片。

❺ 存储每个图片。

❻ 输出到标准输出(stdout);这将被Airflow日志捕获。

❼ 实例化一个PythonOperator来调用Python函数。

❽ 指向要执行的Python函数。

在Airflow中,PythonOperator负责运行任何Python代码。与之前使用的BashOperator一样,此操作器和所有其他操作器都需要一个task_id。当运行一个任务时,会引用该task_id,并在UI中显示出来。使用PythonOperator始终有两个方面:

  1. 我们定义操作器本身(get_pictures)。
  2. python_callable参数指向一个可调用对象,通常是一个函数(_get_pictures)。

当运行操作器时,Python函数将被调用并执行该函数。让我们来详细了解一下。PythonOperator的基本用法始终如图2.5所示。

虽然不是必需的,但为了方便起见,我们将变量名get_pictures设置为与task_id相等。

ini 复制代码
# Ensure directory exists
pathlib.Path("/tmp/images").mkdir(parents=True, exist_ok=True)

可调用函数的第一步是确保存储图片的目录存在,如2.7节中所示。接下来,我们打开从Launch Library API下载的结果,并提取每个发射的图片URL。

csharp 复制代码
with open("/tmp/launches.json") as f:                                  ❶
    launches = json.load(f)                                            ❷
    image_urls = [launch["image"] for launch in launches["results"]]   ❸

❶ 打开火箭发射的JSON文件。

❷ 将其读取为一个字典,以便我们可以操作其中的数据。

❸ 对于每次发射,获取"image"元素。

每个图片URL都被调用以下载图片,并将其保存在/tmp/images目录下。

python 复制代码
for image_url in image_urls:                                 ❶
   try:
       response = requests.get(image_url)                    ❷
       image_filename = image_url.split("/")[-1]             ❸
       target_file = f"/tmp/images/{image_filename}"         ❹
       with open(target_file, "wb") as f:                    ❺
           f.write(response.content)                         ❻
       print(f"Downloaded {image_url} to {target_file}")     ❼
   except requests_exceptions.MissingSchema:                 ❽
       print(f"{image_url} appears to be an invalid URL.")   ❽
   except requests_exceptions.ConnectionError:               ❽
       print(f"Could not connect to {image_url}.")           ❽

❶ 遍历所有图片URL。

❷ 获取图片。

❸ 通过选择最后一个"/"后的所有内容来获取仅文件名。例如,https://host/RocketImages/Electron.jpg_1440.jpg → Electron.jpg_1440.jpg。

❹ 构建目标文件路径。

❺ 打开目标文件句柄。

❻ 将图片写入文件路径。

❼ 输出结果。

❽ 捕获并处理潜在的错误。

在Airflow中运行DAG(有向无环图)

现在我们有了基本的火箭发射DAG,让我们将其运行起来,并在Airflow UI中查看它。Airflow的最低要求包括三个核心组件:调度器、Web服务器和数据库。为了使Airflow运行起来,您可以在Python环境中安装Airflow,或者运行一个Docker容器。

在Python环境中运行Airflow

安装和运行Airflow作为Python包从PyPi有几个步骤:

pip install apache-airflow

请确保安装的是apache-airflow,而不是airflow。在2016年加入Apache Foundation后,PyPi上的airflow存储库被重命名为apache-airflow。由于许多人仍然安装airflow而不是移除旧存储库,它被保留为一个虚拟包,向所有人提供指向正确存储库的消息。

有些操作系统自带Python安装。只运行pip install apache-airflow将会在这个"系统"环境中安装Airflow。在Python项目中工作时,希望将每个项目保持在其自己的Python环境中,以创建一个可复现的Python包集,并避免依赖冲突。这样的环境可以通过以下工具来创建:

在安装完Airflow之后,通过初始化元数据存储(用于存储所有Airflow状态的数据库),创建一个用户,将火箭发射DAG复制到DAGs目录,并启动调度器和Web服务器来启动Airflow:

  1. airflow db init
  2. airflow users create --username admin --password admin --firstname Anonymous --lastname Admin --role Admin --email admin@example.org
  3. cp download_rocket_launches.py ~/airflow/dags/
  4. airflow webserver
  5. airflow scheduler

请注意,调度器和Web服务器都是持续运行的进程,它们会保持您的终端处于打开状态。因此,您可以通过airflow webserver在后台运行,或者打开第二个终端窗口分别运行调度器和Web服务器。设置好后,打开 http:/ /localhost:8080,使用用户名"admin"和密码"admin"登录以查看Airflow。

在Docker容器中运行Airflow

Docker容器也是创建隔离环境的流行选择,用于运行可重现的Python包集,避免依赖冲突。然而,Docker容器在操作系统级别上创建了一个隔离的环境,而Python环境仅在Python运行时级别上进行隔离。因此,您可以创建包含不仅是一组Python包,还包括其他依赖项(如数据库驱动程序或GCC编译器)的Docker容器。在本书中,我们将在几个示例中演示Airflow在Docker容器中运行。

在运行Docker容器之前,您需要在计算机上安装Docker Engine。然后,您可以使用以下命令在Docker中运行Airflow。

less 复制代码
docker run \
-ti \
-p 8080:8080 \                                                             ❶
-v ➥ /path/to/dag/download_rocket_launches.py:/opt/airflow/dags/          ❷
    download_rocket_launches.py \                                          ❷
--entrypoint=/bin/bash \
--name airflow \
apache/airflow:2.0.0-python3.8 \                                           ❸
-c '( \
airflow db init && \                                                       ❹
➥ airflow users create --username admin --password admin --firstname      ❺
    Anonymous --lastname Admin --role Admin --email admin@example.org \    ❺
); \
airflow webserver & \                                                      ❻
airflow scheduler \                                                        ❼
'

❶ 将主机端口8080映射到容器端口。

❷ 挂载DAG文件到容器中。

❸ Airflow Docker镜像。

❹ 在容器中初始化元数据存储。

❺ 创建用户。

❻ 启动Web服务器。

❼ 启动调度器。

注意:如果您熟悉Docker,您可能会认为在一个单独的Docker容器中运行多个进程(如清单2.10所示)是不可取的。这个命令是为了演示目的而设计的,让您能够快速启动Airflow。在生产环境中,您应该将Airflow的Web服务器、调度器和元数据存储放在单独的容器中,这在第10章中有详细解释。

这个命令将下载并运行Airflow Docker镜像apache/airflow。一旦运行,您可以通过http:/ /localhost:8080查看Airflow,并使用用户名"admin"和密码"admin"登录。

查看Airflow用户界面

在http:/ /localhost:8080上首次访问Airflow,您将看到登录界面,如图2.6所示。

登录后,您可以查看download_rocket_launches DAG,如图2.7所示。

这是您将看到的Airflow的第一个印象。目前,唯一的DAG是download_rocket_launches,在DAGs目录中对Airflow可用。主视图上有很多信息,但让我们先检查download_rocket_launches DAG。点击DAG名称以打开它,并查看所谓的图形视图(图2.8)。

这个视图显示了我们提供给Airflow的DAG脚本的结构。一旦放置在DAGs目录中,Airflow将读取脚本并提取出一起形成DAG的各个部分,以便在UI中可视化。图形视图显示了DAG的结构,以及DAG中所有任务是如何连接和运行的顺序。这是您在开发工作流时可能最常使用的视图之一。

状态图例显示了运行时可能看到的所有颜色,所以让我们看看会发生什么并运行DAG。首先,DAG需要处于"on"的状态才能运行;切换按钮以激活DAG。接下来,点击播放按钮以运行它。

触发DAG后,它将开始运行,您将看到工作流的当前状态用颜色表示(图2.9)。由于我们在任务之间设置了依赖关系,连续的任务只有在前面的任务完成后才开始运行。让我们检查notify任务的结果。在实际用例中,您可能希望发送电子邮件或例如Slack通知来通知有关新图片的信息。为了简单起见,它现在只会输出已下载图片的数量。让我们查看日志。

所有任务日志都会被Airflow收集,因此我们可以在UI中搜索输出或在任务失败时查找潜在问题。点击已完成的notify任务,您将看到一个弹出窗口,其中有几个选项,如图2.10所示。

点击顶部中央的"Log"按钮来查看日志,如图2.11所示。日志默认情况下相当冗长,但显示了日志中下载的图片数量。最后,我们可以打开/tmp/images目录并查看这些图片。在Docker中运行时,此目录仅存在于Docker容器内部,而不会存在于您的主机系统中。因此,您必须首先进入Docker容器:

bash 复制代码
docker exec -it airflow /bin/bash

之后,您会在容器中获得一个Bash终端,并可以查看/tmp/images中的图片(如图2.12所示)。

定期运行

火箭爱好者John现在很高兴,因为他已经在Airflow中运行了一个工作流,他可以偶尔触发,以收集最新的火箭图片。他可以在Airflow UI中查看工作流的状态,这已经比他之前在命令行中运行的脚本有了改进。但他仍然需要定期手动触发工作流,这可能是可以自动化的。毕竟,没有人喜欢做计算机本身擅长的重复任务。

在Airflow中,我们可以安排一个DAG在特定的时间间隔内运行,例如每小时、每天或每月一次。这由DAG的schedule_interval参数来控制。

ini 复制代码
dag = DAG(
   dag_id="download_rocket_launches",
   start_date=airflow.utils.dates.days_ago(14),
   schedule_interval="@daily",                     ❶
)

❶ Airflow中的别名为0 0 * * *(即午夜)。

将schedule_interval设置为@daily告诉Airflow每天运行这个工作流,这样John就不必每天手动触发它。这个行为在树状视图中最好看到,如图2.13所示。

树状视图类似于图形视图,但会随着时间的推移显示图形结构。单个工作流所有运行的状态概览如图2.14所示。

DAG的结构以"行和列"布局显示,特别是特定DAG的所有运行状态,其中每一列表示某个时间点上的单个运行。

当我们将schedule_interval设置为@daily时,Airflow知道它每天必须运行一次该DAG。考虑到DAG提供的start_date是14天前,这意味着从14天前到现在的时间可以分为14个等时间间隔的一天。由于这14个时间间隔的开始和结束日期都在过去,所以一旦我们向Airflow提供了schedule_interval,它们就会开始运行。有关schedule_interval的语义以及各种配置方式的更多详细信息在第3章中详细介绍。

处理失败的任务

到目前为止,我们在Airflow UI中只看到了绿色。但是如果发生故障会怎么样呢?任务失败并不少见,可能有多种原因(例如,外部服务停机、网络连接问题或磁盘损坏)。

例如,假设在获取John的火箭图片时发生了网络故障。结果,Airflow任务失败,我们在Airflow UI中看到了失败的任务。它会像图2.15所示。

该特定失败的任务将在图形视图和树状视图中以红色显示,因为无法从互联网获取图片,从而引发错误。随后的notify任务将根本不会运行,因为它依赖于get_pictures任务的成功状态。这些任务实例显示为橙色。默认情况下,所有先前的任务都必须成功运行,任何失败任务的后续任务都不会运行。

让我们通过再次检查日志来找出问题。打开get_pictures任务的日志(图2.16)。

在堆栈跟踪中,我们发现了问题的可能原因:

csharp 复制代码
urllib3.exceptions.NewConnectionError:
    <urllib3.connection.HTTPSConnection object at 0x7f37963ce3a0>: 
    Failed to establish a new connection: 
    [Errno -2] Name or service not known

这表明urllib3(即Python的HTTP客户端)正在尝试建立连接,但无法成功,这可能暗示着防火墙规则阻止了连接或没有互联网连接。假设我们已经解决了这个问题(例如,插入了互联网电缆),让我们重新启动任务。

注意:不需要重新启动整个工作流。Airflow的一个很好的特性是您可以从故障点重新启动,而无需重新启动任何之前成功的任务。

点击失败的任务,然后点击弹出窗口中的"Clear"按钮(图2.17)。它会显示您要清除的任务,意味着您将重置这些任务的状态,并且Airflow将重新运行它们,如图2.18所示。

点击"OK!",失败的任务及其后续任务将被清除,如图2.19所示。

假设连接问题已解决,现在任务将成功运行,并使整个树状视图变为绿色(图2.20)。

在任何软件中,失败的原因有很多。在Airflow工作流中,有时接受失败,有时不接受,有时只在特定条件下接受。处理失败的条件可以在工作流的任何层级上进行配置,并在第4章中详细介绍。

在清除了失败的任务后,Airflow将自动重新运行这些任务。如果一切顺利,John现在将已经下载了因失败任务而导致的火箭图片。请注意,在download_launches任务中调用的URL仅请求下一个火箭发射,这意味着它将在调用API时返回下一个火箭发射的信息。将DAG运行时上下文融入您的代码在第4章中有详细介绍。

总结

  • 在Airflow中,工作流程以DAGs表示。
  • Operators表示单个工作单元。
  • Airflow包含各种类型的操作符,用于处理通用和特定类型的工作。
  • Airflow UI提供图形视图以查看DAG的结构,以及树状视图以查看DAG随时间的运行情况。
  • 可以在DAG的任何位置重新启动失败的任务。
相关推荐
奔跑吧邓邓子2 小时前
大数据利器Hadoop:从基础到实战,一篇文章掌握大数据处理精髓!
大数据·hadoop·分布式
说私域3 小时前
基于定制开发与2+1链动模式的商城小程序搭建策略
大数据·小程序
hengzhepa4 小时前
ElasticSearch备考 -- Async search
大数据·学习·elasticsearch·搜索引擎·es
_.Switch5 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
GZ_TOGOGO5 小时前
【2024最新】华为HCIE认证考试流程
大数据·人工智能·网络协议·网络安全·华为
韩楚风6 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
狼头长啸李树身7 小时前
眼儿媚·秋雨绵绵窗暗暗
大数据·网络·服务发现·媒体
Json_181790144808 小时前
商品详情接口使用方法和对接流程如下
大数据·json
Data 3178 小时前
Hive数仓操作(十七)
大数据·数据库·数据仓库·hive·hadoop
_.Switch11 小时前
Python机器学习:自然语言处理、计算机视觉与强化学习
python·机器学习·计算机视觉·自然语言处理·架构·tensorflow·scikit-learn