跳到正文
cccskills
免费在 GitHub 公开

developing-new-io-connectors

Build Apache Beam connectors that read and write external data. This guide covers Java implementation, schema support for structured records, access from Python and Go, Managed API integration, and testing.

中文简介正在准备中。当前显示英语简介。

原文查看原文说明

End-to-end guide on developing new Apache Beam I/O connectors correctly, including core IO transforms, SchemaTransforms, URN proto definitions, Managed API integration, cross-language expansion service, and testing.

查看安装方法

适用场景

  • Add a connector for an external data system
  • Make a Java connector available to Python and Go
  • Integrate a connector with Beam YAML and the Managed API
  • Review data splitting and retry behavior

包含的文件(1)

  • SKILL.md14.4 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Developing New Apache Beam I/O Connectors

This guide outlines the modern best practices and mandatory steps for building new Apache Beam I/O connectors. Modern Beam connectors are expected to be schema-aware, available in cross-language (Python, Go) pipelines via the Expansion Service, and seamlessly integrable with Beam YAML and the Managed I/O API.

1. Module Structure and Gradle Setup

New Java I/O connectors should reside under sdks/java/io/<connector-name>.

Directory Layout

sdks/java/io/<connector-name>/
├── build.gradle
└── src/
    ├── main/java/org/apache/beam/sdk/io/<connector-name>/
    │   ├── <Connector>IO.java
    │   ├── <Connector>ReadSchemaTransformProvider.java
    │   └── <Connector>WriteSchemaTransformProvider.java
    └── test/java/org/apache/beam/sdk/io/<connector-name>/
        ├── <Connector>IOTest.java
        └── <Connector>ReadSchemaTransformProviderTest.java

Gradle Configuration (build.gradle)

Your build.gradle must use standard Beam Java module conventions and explicitly declare necessary dependencies.

plugins { id 'org.apache.beam.module' }
applyJavaNature(
    // If <connector-name> contains hyphens, convert them to dots or underscores
    automaticModuleName: 'org.apache.beam.sdk.io.<connector_name>',
)

description = "Apache Beam :: SDKs :: Java :: IO :: <Connector Name>"
ext.summary = "Integration with <External System>."

dependencies {
    implementation project(path: ":sdks:java:core", configuration: "shadow")
    implementation project(path: ":model:pipeline", configuration: "shadow") // For URN definitions

    // Add external client libraries here
    implementation library.java.<client_dependency>

    // Handle strict dependency checking if necessary
    permitUnusedDeclared library.java.<client_dependency>

    // Standard test dependencies
    testImplementation project(path: ":sdks:java:core", configuration: "shadowTest")
    testImplementation library.java.junit
}

2. Core I/O Transform Implementation (<Connector>IO.java)

Follow Beam's canonical AutoValue builder pattern for user-facing API configuration. While core Java I/O connectors can be strongly typed using specific domain classes or Java generics (<T>) for idiomatic Java SDK usage, modern sources should also emphasize Beam Row and Schema support (e.g., via .readRows()). For excellent real-world implementations of this pattern, refer to IcebergIO and DeltaIO.

Bounded & Unbounded Sources

Instead of legacy Source classes, implement reading via Beam's Splittable DoFns (SDF) framework for advanced features such as dynamic rebalancing and watermark support.

A primary read transform (such as read() or readRows()) typically extends PTransform<PBegin, PCollection<T>> (or PCollection<Row>). Using PCollection as input is meant for "ReadAll" operations (such as reading a collection of file patterns or queries).

An example SDF-based read transform is given below:

public class MyIO {
  public static ReadRows readRows() {
    return new AutoValue_MyIO_ReadRows.Builder().build();
  }

  @AutoValue
  public abstract static class ReadRows extends PTransform<PBegin, PCollection<Row>> {
    public abstract @Nullable String getConfigurationOption();
    public abstract @Nullable Schema getSchema();
    public abstract Builder toBuilder();

    @AutoValue.Builder
    public abstract static class Builder {
      public abstract Builder setConfigurationOption(String value);
      public abstract Builder setSchema(Schema schema);
      public abstract ReadRows build();
    }

    public ReadRows withConfigurationOption(String value) {
      return toBuilder().setConfigurationOption(value).build();
    }

    public ReadRows withSchema(Schema schema) {
      return toBuilder().setSchema(schema).build();
    }

    @Override
    public PCollection<Row> expand(PBegin input) {
      return input
          // `ReaderDoFn` is an SDF or source implementation that reads records and outputs `Row` objects.
          .apply(ParDo.of(new ReaderDoFn(getConfigurationOption())))
          .setRowSchema(getSchema());
    }
  }

  public static WriteRows writeRows() {
    return new AutoValue_MyIO_WriteRows.Builder().build();
  }

  @AutoValue
  public abstract static class WriteRows extends PTransform<PCollection<Row>, PDone> {
    public abstract @Nullable String getConfigurationOption();
    public abstract Builder toBuilder();

    @AutoValue.Builder
    public abstract static class Builder {
      public abstract Builder setConfigurationOption(String value);
      public abstract WriteRows build();
    }

    public WriteRows withConfigurationOption(String value) {
      return toBuilder().setConfigurationOption(value).build();
    }

    @Override
    public PDone expand(PCollection<Row> input) {
      input.apply("WriteRecords", ParDo.of(new WriterDoFn(getConfigurationOption())));
      return PDone.in(input.getPipeline());
    }
  }
}
  • Please make sure that any code you add adheres to the Beam coding standards. These standards are documented here: https://beam.apache.org/contribute/code-guidelines/

  • Especially scrutinize any logic that involves splitting the data for parallel processing since it is a common source of errors that can lead to data loss or data duplication related issues.

Developing Sinks (Write Transforms)

When implementing data egress (Write transforms), avoid creating single-worker bottlenecks. Depending on your target system's transactional requirements, prefer one of the following canonical Beam sink patterns:

  1. DoFn-Based / Batching Sinks: For external APIs or messaging systems (e.g., Kafka, Pub/Sub, NoSQL databases), use a DoFn that manages connections per bundle (@StartBundle, @FinishBundle) or utilizes GroupIntoBatches to perform highly efficient, parallel batched requests.
  2. Two-Phase Commit / Exactly-Once Sinks: For transactional sinks (e.g., Relational DBs, Apache Iceberg, Delta Lake), implement a multi-stage PTransform:
    • Write Shards: Write records in parallel tasks to staging files or temporary transactions, emitting commit descriptors (PCollection<CommitMessage>).
    • Global Commit: Group the commit messages and execute a single final transaction to commit all staged files/shards.
  3. File-Based Sinks: If your connector purely writes files, leverage Beam's FileIO core infrastructure (FileIO.write() / FileIO.Sink) rather than implementing custom file rolling and sharding logic.
  4. Error Reporting (Dead-Letter Queues): Instead of failing the entire pipeline when an invalid element or API error occurs, modern Write transforms should optionally output a PCollection<Row> (or custom WriteResult / PCollectionRowTuple) containing failed records and explicit error metadata.
  • Specially scrutinize any logic that can create duplicate data due to worker failures. Assume that any transform in the pipeline can fail and be retried multiple times by the Beam runner. If the sink does not handle this properly, it can lead to duplicate data in the target system.

3. Extending the Pipeline Model Proto (external_transforms.proto)

To standardize your transform identifier across SDKs, define its URN in Beam's protobuf schema.

  1. Open model/pipeline/src/main/proto/org/apache/beam/model/pipeline/v1/external_transforms.proto.
  2. Add your read/write URNs under the appropriate enum (e.g., ManagedTransforms.Urns).
message ManagedTransforms {
  enum Urns {
    // ... existing entries
    MY_SYSTEM_READ = 15 [(org.apache.beam.model.pipeline.v1.beam_urn) =
      "beam:schematransform:org.apache.beam:my_system_read:v1"];
    MY_SYSTEM_WRITE = 16 [(org.apache.beam.model.pipeline.v1.beam_urn) =
      "beam:schematransform:org.apache.beam:my_system_write:v1"];
  }
}
  1. Re-generate and compile the model protos:
./gradlew :model:pipeline:generateProto :model:pipeline:compileJava

4. Implementing SchemaTransformProvider

To expose your connector to cross-language pipelines and Beam YAML, create a typed SchemaTransformProvider.

@AutoService(SchemaTransformProvider.class)
public class MyReadSchemaTransformProvider extends TypedSchemaTransformProvider<Configuration> {

  @Override
  public String identifier() {
    return getUrn(ExternalTransforms.ManagedTransforms.Urns.MY_SYSTEM_READ);
  }

  @Override
  public String description() {
    return "Reads records from My System and outputs a PCollection of Beam Rows.";
  }

  @Override
  protected SchemaTransform from(Configuration configuration) {
    return new MyReadSchemaTransform(configuration);
  }

  @Override
  public List<String> outputCollectionNames() {
    return Collections.singletonList("output");
  }

  @DefaultSchema(AutoValueSchema.class)
  @AutoValue
  public abstract static class Configuration {
    @SchemaFieldDescription("Configuration option description.")
    public abstract String getConfigurationOption();

    public static Builder builder() {
      return new AutoValue_MyReadSchemaTransformProvider_Configuration.Builder();
    }

    @AutoValue.Builder
    public abstract static class Builder {
      public abstract Builder setConfigurationOption(String value);
      public abstract Configuration build();
    }
  }

  static class MyReadSchemaTransform extends SchemaTransform {
    private final Configuration configuration;

    MyReadSchemaTransform(Configuration configuration) {
      this.configuration = Objects.requireNonNull(configuration, "configuration cannot be null");
    }

    @Override
    public PCollectionRowTuple expand(PCollectionRowTuple input) {
      PCollection<Row> output = input.getPipeline().apply(
          MyIO.readRows().withConfigurationOption(configuration.getConfigurationOption()));
      return PCollectionRowTuple.of("output", output);
    }
  }
}

5. Integrating with Managed API (Managed.java)

Beam's Managed I/O transform provides a unified interface for data ingest/egress. To support it:

  1. Open sdks/java/managed/src/main/java/org/apache/beam/sdk/managed/Managed.java.
  2. Define a public constant identifier:
public static final String MY_SYSTEM = "my_system";
  1. Register your URNs in READ_TRANSFORMS or WRITE_TRANSFORMS:
public static final Map<String, String> READ_TRANSFORMS =
    ImmutableMap.<String, String>builder()
        // ... existing transforms
        .put(MY_SYSTEM, getUrn(ExternalTransforms.ManagedTransforms.Urns.MY_SYSTEM_READ))
        .build();
  1. Update the Javadoc block in Managed.java to list your new connector.

6. Expansion Service Registration

To enable non-Java SDKs (Python, Go) to discover and expand your new connector, include it in the standard Java Expansion Service.

  1. Open sdks/java/io/expansion-service/build.gradle.
  2. Add your module as a runtime dependency:
dependencies {
    // ... existing dependencies
    runtimeOnly project(":sdks:java:io:<connector-name>")
}

7. Python & Beam YAML Integration

Once registered in the expansion service, your SchemaTransform can be utilized in Python and YAML. E.g., for Managed support in Python:

  1. Open sdks/python/apache_beam/transforms/managed.py.
  2. Export your identifier in __all__ and map it to its URN in Read._READ_TRANSFORMS or Write._WRITE_TRANSFORMS:
MY_SYSTEM = 'my_system'

__all__ = [
    # ... existing
    "MY_SYSTEM",
]

class Read(PTransform):
  _READ_TRANSFORMS = {
      # ... existing
      MY_SYSTEM: ManagedTransforms.Urns.MY_SYSTEM_READ.urn,
  }
  1. In sdks/python/apache_beam/transforms/external.py, map the URN to the appropriate Expansion Service jar target in MANAGED_TRANSFORM_URN_TO_JAR_TARGET_MAPPING.

8. Verification and Testing

Verify your new connector thoroughly across multiple abstraction layers:

1. Unit Tests

Test your core builder and SchemaTransformProvider translation.

./gradlew :sdks:java:io:<connector-name>:test

2. Managed API Translation

In ManagedSchemaTransformTranslationTest.java (under sdks/java/managed), you can verify the translation structure of your managed transform. Note that ManagedTest.java generally uses dummy/test providers (TestSchemaTransformProvider) to keep dependencies lightweight.

./gradlew :sdks:java:managed:test

3. Integration Tests (IT)

Create integration tests to test end-to-end data processing against real system instances, including Managed.read(Managed.MY_SYSTEM) usage.

  • Test resources should be managed via ResourceManager classes under the it/ directory.
  • Add GitHub Actions to trigger your tests when changes are made to your connector code. Consider adding one for pre-commit and one for post-commit.

4. Documentation

Add any necessary documentation for your connector under the website/www/site/content/en/documentation/io/built-in/ directory.


[!TIP] Canonical Reference Implementations: When developing a new connector, we highly recommend studying Apache Iceberg (IcebergIO.java) and Delta Lake (DeltaIO.java) as state-of-the-art reference implementations.

For more details see the Developing I/O connectors guide.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Guides adding metadata, extra information attached to data elements, to Apache Beam's WindowedValue. Maps the changes needed across serialization, storage, processing, and runner interfaces so new fields remain available during pipeline execution.

中文简介正在准备中。当前显示英语简介。

  • Adding trace context or drain flags to WindowedValue
  • Checking metadata preservation through Windmill storage
  • Reviewing propagation through grouping and timers
apache/beam86862026年10月19日 更新

Learn Apache Beam's core concepts through Java and Python examples. Understand distributed datasets, processing steps, pipeline execution, and time windows, with guidance on aggregation, late data, error handling, and sharing processing steps across languages.

中文简介正在准备中。当前显示英语简介。

  • Learn how Pipeline, PCollection, and PTransform fit together
  • Understand grouping, aggregation, merging, and splitting
  • Study time windows, output timing, and late data
apache/beam86862026年10月19日 更新

ci-cd

免费

Helps investigate and modify Apache Beam's automated build and test workflows in GitHub Actions. Explains workflow types, failure logs, targeted reruns, local reproduction, and the cloud credentials needed for workflows that access GCP.

中文简介正在准备中。当前显示英语简介。

  • Investigating failed checks on a pull request
  • Rerunning a specific test workflow
  • Reproducing CI test commands locally
apache/beam86862026年10月19日 更新

Navigate Apache Beam contributions from finding an issue to submitting a pull request, a proposed code change, and responding to reviews. Covers environment setup, tests, formatting, licensing requirements, and closer evaluation of changes to core components.

中文简介正在准备中。当前显示英语简介。

  • Prepare a first Apache Beam contribution
  • Organize a pull request and its related issue
  • Check tests and formatting before submission
apache/beam86862026年10月19日 更新

Build and test Apache Beam with Gradle, the system that manages its project tasks. Find relevant configuration files, inspect library dependencies, run formatting checks, publish locally, and investigate build failures.

中文简介正在准备中。当前显示英语简介。

  • Build or test a specific Apache Beam module
  • Inspect library dependencies and version conflicts
  • Run formatting and pre-commit checks
apache/beam86862026年10月19日 更新

Work with Apache Beam I/O connectors, components that read and write external data. Get guidance on connector usage, unit and integration tests, troubleshooting data connections, and the basic structure of new connectors.

中文简介正在准备中。当前显示英语简介。

  • Add BigQuery or Kafka reads and writes to a pipeline
  • Run unit and integration tests for connectors
  • Investigate data source or destination issues
apache/beam86862026年10月19日 更新

查看 apache 的全部技能

报告此技能的问题