关于 deploying-java-sdk-bundles
这是一份 Airflow Java SDK 部署指南,介绍如何将 Java 任务打包并提供给 Worker 使用。内容涵盖 Gradle 和 Maven 构建、日志集成,以及开源 Airflow 和 Astro 的部署方式。
主要功能
- 01使用 Gradle 和 Maven 构建 Bundle
- 02Fat JAR 与 Thin JAR 打包
- 03SDK 日志集成
- 04配置 Worker 的 JRE 和 Bundle
- 05部署至开源 Airflow 或 Astro
适用场景
- 01打包 Java 任务类和 SDK 依赖
- 02将 Bundle 放入协调器扫描的目录
- 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-sdkJAR 读取该值。
与 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.x | airflow-sdk-slf4j | 无——自动发现绑定(会为你引入 slf4j-api)。 |
| Log4j 2 | airflow-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 项目:
-
构建程序包,然后将其放入项目中:
mkdir -p include/jars && cp ../java-bundle/build/bundle/*.jar include/jars/。 -
编辑项目的
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 -
将协调器配置放入项目的
.env(会自动加载)——AIRFLOW__SDK__*值请参阅 configuring-airflow-language-sdks。 -
运行
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 项目。