mcpField
D
deploying-java-sdk-bundles

deploying-java-sdk-bundles

github.com/astronomer云与 DevOps457161 次安装3 周前更新
代码仓库

关于 deploying-java-sdk-bundles

这是一份 Airflow Java SDK 部署指南,介绍如何将 Java 任务打包并提供给 Worker 使用。内容涵盖 Gradle 和 Maven 构建、日志集成,以及开源 Airflow 和 Astro 的部署方式。

主要功能

  1. 01使用 Gradle 和 Maven 构建 Bundle
  2. 02Fat JAR 与 Thin JAR 打包
  3. 03SDK 日志集成
  4. 04配置 Worker 的 JRE 和 Bundle
  5. 05部署至开源 Airflow 或 Astro

适用场景

  1. 01打包 Java 任务类和 SDK 依赖
  2. 02将 Bundle 放入协调器扫描的目录
  3. 03通过 Docker、Kubernetes 或 Astro 部署 Java Bundle

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/astronomer/agents --skill deploying-java-sdk-bundles

安装后在 Claude Code 中输入/deploying-java-sdk-bundles确认已加载。

详细介绍

部署 Java SDK Bundle

Java SDK 部署只有一个制品:bundle——编译后的任务类与 SDK,打包为 JAR(或一个精简 JAR 加上其依赖 JAR)。使用 Gradle 或 Maven 构建,然后将其放入每个 worker 上 JavaCoordinator 扫描的目录(jars_root)。此技能与平台无关;先介绍一次构建方式,再介绍开源和 Astro 两种部署路径。

实验性功能。 Java SDK 处于预览阶段。下方的制品版本以 ${version} 表示;在 SDK 正式发布前,你可能需要自行将制品构建到本地 Maven 仓库中(参见预览构建部分)。

操作顺序: 构建 bundle(此技能)→ 将其放到 jars_root 指向的位置 → 配置协调器(configuring-airflow-language-sdks)。任务代码本身请参见 authoring-java-sdk-tasks。


使用 Gradle 构建(推荐)

应用 SDK 的 Gradle 插件,并在 build.gradle 中声明依赖:

plugins {
    id("org.apache.airflow.sdk") version "${version}"
}

repositories {
    mavenCentral()
}

dependencies {
    annotationProcessor("org.apache.airflow:airflow-sdk-processor:${version}")  // annotation API only
    implementation("org.apache.airflow:airflow-sdk:${version}")
    // Optional logging integration, e.g.:
    // implementation("org.apache.airflow:airflow-sdk-jpl:${version}")
}

airflowBundle {
    mainClass = "com.example.Main"   // your BundleBuilder entry point
    // fatJar = false                // opt out of the single-JAR build (see below)
}

构建:

./gradlew bundle

之后,build/bundle/ 目录中会包含所有必需的 JAR。注意:

  • 只有使用基于注解的 API 时才需要 annotationProcessor 这一行。基于接口的 API 不需要它。
  • 默认情况下,插件会生成一个胖 JAR(通过 Shadow 插件)——一个独立的文件,可避免跨项目依赖冲突。在 airflowBundle 中设置 fatJar = false 可生成精简 JAR;此时还需要部署每个依赖 JAR。
  • Gradle 插件会在构建时验证 mainClass 是否存在(verifyBundleMainClass)。

使用 Maven 构建

导入 BOM,以便在同一处管理制品版本和 supervisor 架构版本:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.airflow</groupId>
      <artifactId>airflow-sdk-bom</artifactId>
      <version>${version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.apache.airflow</groupId>
    <artifactId>airflow-sdk</artifactId>   
  </dependency>
</dependencies>

通过 maven-compiler-plugin 配置注解处理器(仅适用于注解 API),使其不进入运行时类路径。然后选择一种打包方式:

  • 胖 JAR(推荐): 使用 maven-shade-plugin。在其 ManifestResourceTransformer 中,将 <mainClass> 设为你的 BundleBuilder,并添加清单项 Airflow-Supervisor-Schema-Version,其值从 BOM 属性 ${airflow.supervisor.schema.version} 解析(不要硬编码)。mvn package 会将 JAR 写入 target/。
  • 精简 JAR: 使用 maven-jar-plugin 设置 Main-Class,并使用 maven-dependency-plugin(copy-dependencies)将运行时 JAR 收集到 target/bundle/。此时不需要 Airflow-Supervisor-Schema-Version——Airflow 会从类路径中的 airflow-sdk JAR 读取该值。

与 Gradle 不同,Maven 不会在构建时验证 mainClass;值不正确只会在运行时导致失败。


日志集成

若要让任务日志记录进入 Airflow 日志存储(并显示在 UI 的任务日志视图中),每种使用的日志门面都必须在 bundle 中包含恰好一个 SDK 日志制品。版本由 airflow-sdk-bom 管理;Maven 用户使用相同的制品 ID。

选择日志门面。 对于全新项目,优先使用 JPL(System.Logger)——它内置于 JDK,因此任务无需额外的日志 API。只有在集成的库已经通过其他日志门面记录日志时,才选择其他门面,这样它们的日志记录也能进入 Airflow。优先级:JPL > SLF4J = Log4j 2 > JUL;将 JUL 仅视为旧版集成方式,不要在新代码中选择它。

日志门面制品依赖之外的设置
System.Logger(JPL)airflow-sdk-jpl无——通过 ServiceLoader 发现提供程序。
SLF4J 2.xairflow-sdk-slf4j无——自动发现绑定(会为你引入 slf4j-api)。
Log4j 2airflow-sdk-log4j2运行时类路径中需要有 log4j-core + 在 log4j2.xml 中声明 AirflowAppender(见下文)。
java.util.logging(JUL)airflow-sdk-jul在 main() 中调用 AirflowJulHandler.setup()(见下文),或使用 logging.properties 文件(参见 configuring-airflow-language-sdks)。

Log4j 2 — log4j-core 中包含用于发现 appender 的插件加载器(log4j-api 会作为传递依赖引入):

implementation("org.apache.airflow:airflow-sdk-log4j2:${version}")
runtimeOnly("org.apache.logging.log4j:log4j-core:${log4jVersion}")
<Configuration>
  <Appenders>
    <AirflowAppender name="Airflow"/>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="Airflow"/>
    </Root>
  </Loggers>
</Configuration>

JUL — 在任何任务运行前调用 AirflowJulHandler.setup()。它会清除根日志记录器已有的处理器(默认的 ConsoleHandler 会写入 stderr,否则 Airflow 会以 ERROR 级别将其捕获为 task.stderr,导致每条记录重复):

public static void main(String[] args) {
    AirflowJulHandler.setup();
    Server.create(args).serve(new MyBundle().build());
}

不要重复配置提供程序。 若在 airflow-sdk-jpl 之外再配置一个 System.LoggerFinder 实现,或在 airflow-sdk-slf4j 之外再配置一个 SLF4J 绑定(logback-classic、slf4j-simple),提供程序的选择就会变得不可预测。


预览版构建(正式版发布前)

如果你依赖的是正式版,请跳过本节。 固定使用已发布到 Maven Central 的版本(例如 1.0.0)后,上文构建片段中的 mavenCentral() 仓库就足够了。

SDK 尚处于预发布阶段时,文档推荐的方式是从 Airflow 仓库构建制品和 Gradle 插件,并将它们安装到本地 Maven 仓库:

# in apache/airflow's java-sdk/ directory
./gradlew publishToMavenLocal -PskipSigning=true

然后在项目的 pluginManagement(位于 settings.gradle)和项目的 repositories(位于 build.gradle)中都添加 mavenLocal()——SDK 自带的示例项目正是通过这种方式解析它。

将 -SNAPSHOT 制品发布到 Apache 的快照 Nexus 后,可以用该仓库替代本地构建(同样需要添加到上述两个位置):

maven {
    name = "apacheSnapshots"
    url = "https://repository.apache.org/content/repositories/snapshots/"
    mavenContent { snapshotsOnly() }
}

快照会变动;使用 ./gradlew bundle --refresh-dependencies 强制刷新。(对于 Maven,将相同的仓库添加到 <repositories> 和 <pluginRepositories>。)


将 bundle 放到协调器扫描的位置

协调器会递归扫描 jars_root 并自动构建类路径,因此只需复制整个输出目录:

cp build/bundle/* /opt/airflow/jars/    # /opt/airflow/jars == jars_root

工作器还需要 JRE 17+。如何将协调器连接到此目录,请参阅 configuring-airflow-language-sdks。


部署方式

不要求使用 Astronomer 工具——该 SDK 可在任何包含 Task SDK 的 Airflow 上运行。选择符合用户设置的方式。

开源(Docker / Kubernetes)

将 JRE 和 bundle 烘焙到 Airflow 镜像中,或将它们挂载进去:

FROM apache/airflow:3          # pin a specific 3.x in production
USER root
RUN apt-get update \
    && apt-get install -y --no-install-recommends default-jre-headless \
    && apt-get clean && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /opt/airflow/jars
COPY build/bundle/ /opt/airflow/jars/
USER airflow

在 Kubernetes(Helm chart)上,可像上文一样将 JAR 烘焙到自定义镜像中,或通过共享卷挂载;在工作器/调度器上通过环境变量设置 [sdk] 配置。有关更全面的 Docker Compose 和 Helm 工作流,请参阅 deploying-airflow。

Astro(一个可选方案,并非必需)

如果用户使用 Astronomer 的 Astro CLI,同样的思路可以应用于 Astro 项目:

  1. 构建程序包,然后将其放入项目中:mkdir -p include/jars && cp ../java-bundle/build/bundle/*.jar include/jars/。

  2. 编辑项目的 Dockerfile,安装 JRE 并将 JAR 复制到协调器目录:

    FROM quay.io/astronomer/astro-runtime:<version>
    USER root
    RUN apt-get update \
        && apt-get install -y --no-install-recommends default-jre-headless \
        && apt-get clean && rm -rf /var/lib/apt/lists/*
    RUN mkdir -p /opt/airflow/jars
    COPY include/jars/ /opt/airflow/jars/
    USER airflow
    
  3. 将协调器配置放入项目的 .env(会自动加载)——AIRFLOW__SDK__* 值请参阅 configuring-airflow-language-sdks。

  4. 运行 astro dev start(更改后运行 astro dev restart),即可构建镜像并在本地启动 Airflow;按常规使用 astro deploy 部署。

不要凭记忆指定 Astro Runtime / Airflow 版本——请查看生成的 Dockerfile 或查阅最新文档。当 SDK 和 Airflow 3.3 仍处于预览阶段时,可能需要使用 beta/dev Astro Runtime 镜像。


部署检查清单

  • 已构建程序包(./gradlew bundle 或 mvn package),且 mainClass 指向你的 BundleBuilder。
  • 仅当使用注解 API 时,才需要配置 annotationProcessor。
  • JAR 已复制到 worker 的 jars_root 目录;如果使用 thin JAR,也要复制依赖 JAR。
  • worker 上有可用的 JRE 17+。
  • 已配置协调器和 queue_to_coordinator(configuring-airflow-language-sdks)。
  • 如果 jars_root 下有多个可执行 JAR,请显式设置 main_class。

相关技能

  • authoring-java-sdk-tasks:编写 Java 任务代码及对应的 Python 存根。
  • configuring-airflow-language-sdks:注册协调器并路由队列。
  • deploying-airflow:Airflow 通用部署(Astro、Docker Compose、Kubernetes)。
  • setting-up-astro-project:初始化并配置 Astro 项目。

评论

支持 Markdown