Airflow 在气流操作员之间共享大型文件

Airflow 在气流操作员之间共享大型文件,airflow,google-cloud-composer,Airflow,Google Cloud Composer,假设气流DAG由以下两个操作符组成: Op1(GCSToLocalFilesystemOperator):从GCS下载文件XYZ Op2(PythonOperator):需要文件XYZ来处理它 DAG将由GCP的作曲家执行。我知道可以将这两个操作符组合起来,并将它们实现为一个PythonOperator,但我希望它更加模块化,并尽可能多地使用内置操作符 候选解决方案: 使用临时文件:不能使用临时文件。如果XYZ存储为/tmp/XYZ,Op2可能会找到它,也可能找不到,因为这两个操作符可

假设气流DAG由以下两个操作符组成:

  • Op1(
    GCSToLocalFilesystemOperator
    ):从GCS下载文件XYZ

  • Op2(
    PythonOperator
    ):需要文件XYZ来处理它

DAG将由GCP的作曲家执行。我知道可以将这两个操作符组合起来,并将它们实现为一个
PythonOperator
,但我希望它更加模块化,并尽可能多地使用内置操作符

候选解决方案:

  • 使用临时文件:不能使用临时文件。如果XYZ存储为/tmp/XYZ,Op2可能会找到它,也可能找不到,因为这两个操作符可能由不同的工作人员运行

  • xcom:xcom不能在这里使用,因为文件太大了

  • 将GCS用作共享存储:在这个特定示例中它不起作用。我们回到了现在的位置,因为一个运营商仍然需要为第二个运营商下载和利用文件


那么,什么是好的解决方案呢?一般来说,有没有一种方法可以将文件(或字符串)从一个操作符传递到另一个操作符?

是的,中间文件。使用xcom传递文件的路径

我找到了如上所述的解决方案。composer Pod上存在gcsfuse文件系统。在composer代码中,您可以通过
/home/aiffair/gcs
本地访问它

因此,在上面的示例中,Op1需要将XYZ从另一个bucket复制到composer bucket。这可以使用
GCSToGCSOperator
完成:

来自afflow.operators.python\u operator导入PythonOperator
从afflow.providers.google.cloud.transfers.gcs_到_gcs import GCSToGCSOperator
MY_BUCKET='包含XYZ'的原始桶'
PATH_TO_XYZ='PATH/TO/XYZ'
COMPOSER_BUCKET=os.environ.get('GCS_BUCKET'))
XYZ_GCS_路径='data/my_dir/XYZ'
XYZ_LOCAL_PATH=f'/home/afflow/gcs/{XYZ_gcs_PATH}'
def my_函数(文件路径):
将open(filepath)作为f:
content=f.read()
打印(内容)
将models.DAG(…)作为DAG:
Op1=GCSToGCSOperator(
task_id='download_data',
source_bucket=我的_bucket,
source_object=路径_到_XYZ,
destination_bucket=编写器_bucket,
目标对象=XYZ\U GCS\U路径,
)
Op1=蟒蛇算子(
任务\u id='read\u file',
python\u callable=my\u函数,
op_kwargs={'filepath':XYZ_LOCAL_PATH}
)
Op1>>Op2

您说OP2不能直接从地面军事系统读取数据,但没有解释原因。一般来说,这是此类场景的解决方案。将文件上载到共享磁盘。地面军事系统是否在OP2中被完全禁止,或者它是一个特定的存储桶/文件夹?您能否创建一个将用作共享磁盘的存储桶,以使您的OP1成为GcsToGcs?如果没有-那么很抱歉将Op1和Op2合并到一个运营商中,或者升级到Airflow 2并定义一个适合您希望在运营商之间共享的数据大小的XCom后端。谢谢您的评论。正如我所提到的,让Op2直接从GCS读取是没有问题的(实际上我是使用客户机库读取的)。我的目标是模块化代码,并尽可能使用内置操作符,如GCSToLocalFilesystemOperator。我使用的是气流-1.10.12,这是Composer目前提供的。我怀疑我能自己升级。所以我猜这条路径是一条死胡同,这让我想知道GCSToLocalFilesystemOperator是否可以在任何地方使用。我认为它与您的用例无关。您可以做的是创建一个自定义操作符,将OP1和OP2组合成一个新的OP,也可以用于其他dag。这是一种非常常见的做法。你能再详细说明一下你的解决方案吗?什么是中间文件?它是一个气流组件吗?您将数据写入一个文件“/path/to”file”,如果您使用python操作符,您可以将此路径返回以进一步用作xcom,即.kwargs['task\u instance'].xcom\u pull(task\u id='task\u id'),它将返回您通过xcom发送的文件路径。您也可以使用这个内部函数或jinja模板