Skip to main content

3 posts tagged with "Zeta"

View All Tags

· 9 min read
Niu Zhiwei

Submitting a SeaTunnel job may look like a simple submitJob request. Inside the server, however, it passes through multiple stages: Master detection, job coordination, JobMaster initialization, physical execution plan construction, Pipeline resource allocation, and TaskGroup deployment.

Based on the submitJob sequence I organized, this article focuses on one main path: what happens between a job submission request entering SeaTunnel Server and the final call to TaskExecutionService.deployTask() that deploys the TaskGroup.

This article does not cover the thread model inside TaskExecutionService, Task execution details, or data flow. It focuses on the job submission, scheduling, and deployment path.

Core Components

Before walking through the process, let's look at the responsibilities of the key objects on the submitJob path.

ComponentResponsibility
SubmitJobServletReceives external job submission requests and serves as one of the server-side entry points.
JobInfoServiceHandles the job submission entry logic and determines whether the current node is the Master or a Worker.
MasterNodeForwards the job submission request to the Master when the current node is not the Master.
CoordinatorServiceServes as the job coordination entry point, checks whether the job is already running, and creates or manages the JobMaster.
JobMasterActs as the runtime control center for a single Job and initializes the runtime context, classloader, checkpoint configuration, and related resources.
PhysicalPlanRepresents the physical execution plan built from the logical DAG and drives Job-level state transitions.
SubPlanActs as the Pipeline-level scheduling unit and handles resource allocation and Pipeline state transitions.
ResourceUtilsAllocates runtime resources for a Pipeline.
PhysicalVertexRepresents a finer-grained physical execution node and deploys TaskGroups.
TaskExecutionServiceReceives and deploys TaskGroups.

Overall Process

First, the following simplified flowchart provides an overview of the entire path.

This path can be summarized in one sequence:

SubmitJobServlet
-> JobInfoService
-> MasterNode / CoordinatorService
-> JobMaster
-> PhysicalPlan
-> SubPlan
-> PhysicalVertex
-> TaskExecutionService

Let's examine it stage by stage.

Stage 1: The Request Enters JobInfoService

The job submission request first enters SubmitJobServlet and is then handed to JobInfoService.

The key action here is not starting the job immediately. The system first determines: is the node that received the request the Master?

If the current node is the Master, JobInfoService can continue the submission locally. If the current node is a Worker, it forwards the request to the Master through MasterNode.submitJob().

This design ensures that job submission is coordinated centrally by the Master and prevents multiple nodes from creating independent Job scheduling contexts.

Stage 2: CoordinatorService Takes Over

After the request reaches the Master, it proceeds to CoordinatorService.submitJob().

CoordinatorService mainly performs two tasks here:

  1. Determine whether the Job already exists or is running.
  2. For a new job, create and initialize the corresponding JobMaster.

If the job is already running, SeaTunnel does not need to create another scheduling context and can return a successful submission response directly. A new job enters the JobMaster initialization process.

At this point, submitJob has moved from API request handling into the scheduling system.

Stage 3: JobMaster Initialization

JobMaster can be understood as the runtime control center for a Job.

After a JobMaster is created, it performs the preparation required before execution, including:

  • Building the classloader required by the job.
  • Initializing checkpoint-related configuration.
  • Preparing the context required to construct the physical execution plan from the logical DAG.

No Task is deployed at this stage. It prepares the runtime environment for subsequent scheduling.

Stage 4: From the Logical DAG to PhysicalPlan

After JobMaster initialization, SeaTunnel builds a PhysicalPlan from the logical DAG.

One important concept here is that SeaTunnel does not start the entire job at once. It advances execution step by step through a state machine.

At the Job level, the core state transition can be simplified as:

CREATED -> SCHEDULED -> startSubPlanStateProcess

PhysicalPlan drives Job-level state transitions, while actual Pipeline scheduling continues at the SubPlan level.

Stage 5: SubPlan Allocates Resources and Starts Deployment

At the SubPlan level, SeaTunnel's scheduling granularity moves from the entire Job down to an individual Pipeline.

SubPlan.stateProcess() performs different actions according to the current Pipeline state:

The key points at this level are:

  • In the CREATED state, the Pipeline first transitions to SCHEDULED.
  • In the SCHEDULED state, it starts allocating resources through ResourceUtils.applyResourceForPipeline().
  • After resource allocation succeeds, the Pipeline enters DEPLOYING.
  • If resource allocation fails, the Pipeline enters makePipelineFailing(e).

Therefore, a Pipeline is not deployed immediately. It must first obtain the resources required to run.

Stage 6: PhysicalVertex Deploys the TaskGroup

When the Pipeline enters DEPLOYING, the SubPlan starts the PhysicalVertex instances it contains.

PhysicalVertex first updates the Task state to DEPLOYING, then deploys it according to the allocated slotProfile.

Deployment has one important branch: is the target Worker local or remote?

If the target Worker is the current node, SeaTunnel can call the local TaskExecutionService.deployTask(taskGroupInfo) directly.

If the target Worker is remote, SeaTunnel sends the deployment request through DeployTaskOperation. The request ultimately enters TaskExecutionService.deployTask(taskGroupInfo) on the target Worker.

After successful deployment, PhysicalVertex updates the Task state to RUNNING. If deployment fails, it enters makeTaskGroupFailing().

When the TaskGroups inside the Pipeline have been deployed and entered the running state, the SubPlan also transitions to RUNNING.

Failure, Cancellation, and Recovery Branches

In addition to normal submission and deployment, the SubPlan state machine handles failure, cancellation, and recovery.

The following diagram provides a simplified view:

This is why the preceding state-machine design matters:

  • The normal path can advance deployment and execution.
  • The failure path can enter failing and failed states.
  • The cancellation path can enter canceling and canceled states.
  • If recovery conditions are met, the Pipeline can release its resources, allocate them again, and recover.

In other words, the state machine does not exist merely to make the process more complex. It makes the job lifecycle controllable.

Complete Sequence Diagram

Finally, the following sequence diagram connects the main process and makes the overall call order easier to follow.

Summary

The core logic after SeaTunnel receives a job submission is not simply to start the job immediately.

It generally follows this main path:

SubmitJobServlet
-> JobInfoService
-> MasterNode / CoordinatorService
-> JobMaster
-> PhysicalPlan
-> SubPlan
-> PhysicalVertex
-> TaskExecutionService

In this process:

  • JobInfoService handles the submission entry point and determines whether the request must be forwarded to the Master.
  • CoordinatorService coordinates the job, prevents duplicate submissions, and creates the JobMaster.
  • JobMaster initializes the Job runtime context.
  • PhysicalPlan drives Job-level state transitions.
  • SubPlan handles Pipeline-level resource allocation and scheduling.
  • PhysicalVertex deploys TaskGroups.
  • TaskExecutionService is the final entry point for TaskGroup deployment.

After understanding this path, it becomes easier to place SeaTunnel's Task execution thread model, data flow, and checkpoint mechanism in the correct part of the architecture.

· 8 min read
Daniel

Tongcheng Travel's data channel evolved over several years into four parallel systems for offline transfer, real-time integration, Sqoop jobs, and SeaTunnel jobs. Each system solved a problem at a particular stage, but their overlapping capabilities, different execution engines, and separate operational models eventually became a barrier to platform-wide governance.

At an Apache SeaTunnel Meetup, Xiaochen Zhou, who works on the data platform at Tongcheng Travel, explained how the company consolidated those systems into a unified batch and streaming data channel based on the Apache SeaTunnel Zeta Engine. The project had three non-negotiable goals: keep the migration transparent to application teams, prove data consistency before switching traffic, and improve execution efficiency and operational stability.

This article summarizes the architecture, migration safeguards, AI-assisted task generation, validation design, and future direction presented in that session.

· 5 min read

In large-scale data integration, the throughput bottleneck is often not the data pipeline itself, but the “metadata path”: loading connector JARs during startup, managing state and recovery during runtime, and fetching schemas/partitions from external systems (databases, Hive Metastore, etc.) while initializing jobs. Once job concurrency reaches thousands (or more), these seemingly small operations can easily turn into cluster-wide pressure.

Apache SeaTunnel Engine (Zeta) caches high-frequency, reusable, and expensive metadata on the engine side, and combines it with distributed storage and lifecycle cleanup. This is a key reason why the engine can run massive numbers of sync jobs concurrently with better stability.

Metadata flow in SeaTunnel’s distributed architecture

Why metadata becomes the bottleneck

When you start a huge number of small jobs in parallel, the most common metadata bottlenecks usually come from three areas:

  • Class loading and dependency isolation: creating a dedicated ClassLoader per job can repeatedly load the same connector dependencies and quickly raise JVM Metaspace pressure.
  • State and recoverability: checkpoints, runtime state, and historical job information can become heavy in both memory and IO without tiered storage and automatic cleanup.
  • External schema/catalog queries: repeated schema and partition lookups can overload databases or Hive Metastore and lead to instability.

Below is a practical breakdown of SeaTunnel’s approach, together with configuration tips you can apply in production.

1) ClassLoader caching to reduce Metaspace pressure

When many jobs reuse the same set of connectors, frequent creation/destruction of class loaders causes Metaspace churn and can even lead to metaspace-related OOMs. SeaTunnel Engine provides classloader-cache-mode to reuse class loaders across jobs and reduce repeated loads.

Enable it in seatunnel.yaml (it is enabled by default; re-enable it if you previously turned it off):

seatunnel:
engine:
classloader-cache-mode: true

When it helps most:

  • High job concurrency and frequent job starts, with a relatively small set of connector types.
  • You observe consistent Metaspace growth or class-loading related memory alerts.

Notes:

  • If your cluster runs with a highly diverse set of connectors, caching increases the amount of resident metadata in Metaspace. Monitor your Metaspace trend and adjust accordingly.

2) Distributed state and persistence for recoverability

SeaTunnel Engine’s fault tolerance is built on the Chandy–Lamport checkpoint idea. For both performance and reliability, it uses Hazelcast distributed data structures (such as IMap) for certain runtime information, and relies on external storage (shared/distributed storage) for durable recovery.

In practice, you will usually care about three sets of settings:

(1) Checkpoint parameters

seatunnel:
engine:
checkpoint:
interval: 300000
timeout: 10000

If your job config (env) specifies checkpoint.interval/checkpoint.timeout, the job config takes precedence.

For multi-node clusters, configure at least backup-count to reduce the risk of losing in-memory information when a node fails. If you want jobs to be automatically recoverable after a full cluster stop/restart, consider enabling external persistence for IMap as well.

For details, see:

  • /docs/seatunnel-engine/deployment
  • /docs/seatunnel-engine/checkpoint-storage

(3) Automatic cleanup of historical job information

SeaTunnel stores completed job status, counters, and error logs in IMap. As the number of jobs grows, memory usage will grow too. Configure history-job-expire-minutes so expired job information is evicted automatically (default is 1440 minutes, i.e., 1 day).

seatunnel:
engine:
history-job-expire-minutes: 1440

3) Catalog/schema metadata caching to reduce source-side pressure

When many jobs start concurrently, schema/catalog requests (table schema, partitions, constraints, etc.) can turn into a “silent storm”. SeaTunnel applies caching and reuse patterns in connectors/catalogs to reduce repeated network round-trips and metadata parsing overhead.

  • JDBC sources: startup typically fetches table schemas, types, and primary keys for validation and split planning. For large fan-out startups, avoid letting every job repeatedly fetch the same metadata (batch job starts or pre-warming can help).
  • Hive sources: Hive Metastore is often a shared and sensitive service. Reusing catalog instances and already-loaded database/table/partition metadata helps reduce Metastore pressure, especially for highly partitioned tables.

How this differs from Flink/Spark: optimized for “massive small jobs”

Flink is primarily designed for long-running streaming jobs and complex operator state; Spark is job/context oriented for batch processing. For the “tens of thousands of independent small jobs” goal, SeaTunnel Engine focuses on pushing reusable metadata down to the engine layer: minimizing repeated loads, minimizing repeated external queries, and managing the lifecycle of historical job metadata to keep the cluster stable under high concurrency.

Production checklist

  • Enable reasonable backups: in production, set backup-count >= 1 and evaluate IMap persistence if you need automatic recovery after full restarts.
  • Limit connector diversity: keeping connector combinations relatively stable improves the benefit of classloader-cache-mode.
  • Monitor metadata-related signals: besides JVM metrics, watch checkpoint latency/failure rate, Hazelcast memory usage, IMap size and growth, and historical job accumulation.
  • Set eviction policies: tune history-job-expire-minutes to balance observability and long-term memory safety.

Example dashboard for metadata-related signals