Python xác định loại tham số

Hướng dẫn lập trình Beam dành cho người dùng Beam muốn sử dụng Beam SDK để tạo quy trình xử lý dữ liệu. Nó cung cấp hướng dẫn sử dụng các lớp Beam SDK để xây dựng và kiểm tra quy trình của bạn. Hướng dẫn lập trình không nhằm mục đích tham khảo toàn diện, mà là hướng dẫn cấp cao, không phụ thuộc vào ngôn ngữ để lập trình quy trình Beam của bạn. Khi hướng dẫn lập trình được điền vào, văn bản sẽ bao gồm các mẫu mã bằng nhiều ngôn ngữ để giúp minh họa cách triển khai các khái niệm Beam trong quy trình của bạn

Nếu bạn muốn giới thiệu ngắn gọn về các khái niệm cơ bản của Beam trước khi đọc hướng dẫn lập trình, hãy xem trang Khái niệm cơ bản về mô hình Beam

Thích ứng cho
  • SDK Java
  • SDK Python
  • Truy cập SDK
  • SDK TypeScript

SDK Python hỗ trợ Python 3. 7, 3. 8, 3. 9 và 3. 10

Go SDK hỗ trợ Go v1. 18+. Bản phát hành SDK 2. 32. 0 là phiên bản thử nghiệm cuối cùng

Typescript SDK hỗ trợ Node v16+ và vẫn đang thử nghiệm

1. Tổng quan

Để sử dụng Beam, trước tiên bạn cần tạo một chương trình trình điều khiển bằng cách sử dụng các lớp trong một trong các Beam SDK. Chương trình trình điều khiển của bạn xác định đường dẫn của bạn, bao gồm tất cả đầu vào, biến đổi và đầu ra; . Chúng bao gồm Trình chạy đường ống, đến lượt nó, xác định đường ống của bạn sẽ chạy trên back-end nào

Beam SDK cung cấp một số khái niệm trừu tượng giúp đơn giản hóa cơ chế xử lý dữ liệu phân tán quy mô lớn. Các bản tóm tắt Beam giống nhau hoạt động với cả nguồn dữ liệu hàng loạt và luồng dữ liệu. Khi bạn tạo quy trình Beam, bạn có thể nghĩ về tác vụ xử lý dữ liệu của mình theo các khái niệm trừu tượng này. Chúng bao gồm

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68. Một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 gói gọn toàn bộ tác vụ xử lý dữ liệu của bạn, từ đầu đến cuối. Điều này bao gồm đọc dữ liệu đầu vào, chuyển đổi dữ liệu đó và ghi dữ liệu đầu ra. Tất cả các chương trình trình điều khiển Beam phải tạo một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68. Khi bạn tạo
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68, bạn cũng phải chỉ định các tùy chọn thực thi cho biết địa điểm và cách chạy của
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73. A
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 represents a distributed data set that your Beam pipeline operates on. The data set can be bounded, meaning it comes from a fixed source like a file, or unbounded, meaning it comes from a continuously updating source via a subscription or other mechanism. Your pipeline typically creates an initial
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 by reading data from an external data source, but you can also create a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 from in-memory data within your driver program. From there,
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73s are the inputs and outputs for each step in your pipeline

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78. A
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 represents a data processing operation, or a step, in your pipeline. Every
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 takes one or more
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 objects as input, performs a processing function that you provide on the elements of that
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73, and produces zero or more output
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 objects

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    84. The Go SDK has an explicit scope variable used to build a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68. A
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 can return it’s root scope with the
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    87 method. The scope variable is passed to
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 functions to place them in the
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 that owns the
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    84
  • I/O transforms. Beam comes with a number of “IOs” - library
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78s that read or write data to various external storage systems

A typical Beam driver program works as follows

  • Create a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 object and set the pipeline execution options, including the Pipeline Runner
  • Create an initial
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 for pipeline data, either using the IOs to read data from an external storage system, or using a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    94 transform to build a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 from in-memory data
  • Apply
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78s to each
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73. Transforms can change, filter, group, analyze, or otherwise process the elements in a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73. A transform creates a new output
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 without modifying the input collection. A typical pipeline applies subsequent transforms to each new output
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 in turn until processing is complete. However, note that a pipeline does not have to be a single straight line of transforms applied one after another. think of
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73s as variables and
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78s as functions applied to these variables. the shape of the pipeline can be an arbitrarily complex processing graph
  • Use IOs to write the final, transformed
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73[s] to an external source
  • Run the pipeline using the designated Pipeline Runner

When you run your Beam driver program, the Pipeline Runner that you designate constructs a workflow graph of your pipeline based on the

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects you’ve created and transforms that you’ve applied. That graph is then executed using the appropriate distributed processing back-end, becoming an asynchronous “job” [or equivalent] on that back-end

2. Creating a pipeline

The

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 abstraction encapsulates all the data and steps in your data processing task. Your Beam driver program typically starts by constructing a Pipeline Pipeline object, and then using that object as the basis for creating the pipeline’s data sets as
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s and its operations as
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
07s.

To use Beam, your driver program must first create an instance of the Beam SDK class

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 [typically in the
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
09 function]. Khi bạn tạo
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68, bạn cũng sẽ cần đặt một số tùy chọn cấu hình. You can set your pipeline’s configuration options programmatically, but it’s often easier to set the options ahead of time [or read them from the command line] and pass them to the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 object when you create the object

A Pipeline in the Typescript API is simply a function that will be called with a single `root` object and is passed to a Runner's `run` method

// Start by defining the options for the pipeline.
PipelineOptions options = PipelineOptionsFactory.create[];

// Then create the pipeline.
Pipeline p = Pipeline.create[options];

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];

2. 1. Configuring pipeline options

Use the pipeline options to configure different aspects of your pipeline, such as the pipeline runner that will execute your pipeline and any runner-specific configuration required by the chosen runner. Your pipeline options will potentially include information such as your project ID or a location for storing files

When you run the pipeline on a runner of your choice, a copy of the PipelineOptions will be available to your code. For example, if you add a PipelineOptions parameter to a DoFn’s

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 method, it will be populated by the system

2. 1. 1. Đặt PipelineOptions từ đối số dòng lệnh

Mặc dù bạn có thể định cấu hình quy trình của mình bằng cách tạo đối tượng

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 và đặt trường trực tiếp, nhưng Beam SDK bao gồm trình phân tích cú pháp dòng lệnh mà bạn có thể sử dụng để đặt trường trong
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 bằng cách sử dụng đối số dòng lệnh

Để đọc các tùy chọn từ dòng lệnh, hãy xây dựng đối tượng

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 của bạn như được minh họa trong mã ví dụ sau

Sử dụng cờ Go để phân tích các đối số dòng lệnh để định cấu hình đường dẫn của bạn. Cờ phải được phân tích cú pháp trước khi

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
16 được gọi

Bất kỳ đối tượng Javascript nào cũng có thể được sử dụng làm tùy chọn đường dẫn. Người ta có thể xây dựng một cách thủ công, nhưng cũng thường truyền một đối tượng được tạo từ các tùy chọn dòng lệnh, chẳng hạn như

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
17

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];

Điều này diễn giải các đối số dòng lệnh tuân theo định dạng

--=

Việc thêm phương thức

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
18 sẽ kiểm tra các đối số dòng lệnh được yêu cầu và xác thực các giá trị đối số

Building your

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 this way lets you specify any of the options as a command-line argument

Defining flag variables this way lets you specify any of the options as a command-line argument

Ghi chú. Đường dẫn ví dụ về WordCount trình bày cách đặt các tùy chọn đường dẫn trong thời gian chạy bằng cách sử dụng các tùy chọn dòng lệnh

2. 1. 2. Tạo tùy chọn tùy chỉnh

Bạn có thể thêm các tùy chọn tùy chỉnh của riêng mình ngoài

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 tiêu chuẩn

To add your own options, define an interface with getter and setter methods for each option

The following example shows how to add
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
21 and
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
22 custom options

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
0

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
1

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
2

You can also specify a description, which appears when a user passes

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
23 as a command-line argument, and a default value

You set the description and default value using annotations, as follows

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
3

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
4

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
5

For Python, you can also simply parse your custom options with argparse; there is no need to create a separate PipelineOptions subclass

It’s recommended that you register your interface with

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24 and then pass the interface when creating the
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 object. When you register your interface with
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24, the
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
23 can find your custom options interface and add it to the output of the
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
23 command.
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24 will also validate that your custom options are compatible with all other registered options

The following example code shows how to register your custom options interface with

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
6

Now your pipeline can accept

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
31 and
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
32 as command-line arguments

3. PCollections

The PCollection

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 abstraction represents a potentially distributed, multi-element data set. You can think of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as “pipeline” data; Beam transforms use
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects as inputs and outputs. Như vậy, nếu bạn muốn làm việc với dữ liệu trong quy trình của mình, dữ liệu đó phải ở dạng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73.

After you’ve created your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68, you’ll need to begin by creating at least one
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 in some form. The
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 you create serves as the input for the first operation in your pipeline

3. 1. Creating a PCollection

You create a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by either reading data from an external source using Beam’s , or you can create a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of data stored in an in-memory collection class in your driver program. The former is typically how a production pipeline would ingest data; Beam’s Source APIs contain adapters to help you read from external sources like large cloud-based files, databases, or subscription services. The latter is primarily useful for testing and debugging purposes

3. 1. 1. Reading from an external source

To read from an external source, you use one of the . The adapters vary in their exact usage, but all of them read from some external data source and return a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 whose elements represent the data records in that source

Each data source adapter has a

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
43 transform; to read, you must apply that transform to the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 object itself.
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
45
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
46
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
47
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
48
, for example, reads from an external text file and returns a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 whose elements are of type
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50, each
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50 represents one line from the text file. Here’s how you would apply
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
45
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
46
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
47
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
48
to your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 root to create a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
7

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
8

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
9

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
0

See the to learn more about how to read from the various data sources supported by the Beam SDK

3. 1. 2. Creating a PCollection from in-memory data

To create a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 from an in-memory Java
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
59, you use the Beam-provided
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 transform. Much like a data adapter’s
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
43, you apply
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 directly to your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 object itself

As parameters,

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 accepts the Java
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
59 and a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 object. The
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 specifies how the elements in the
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
59 should be

To create a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 from an in-memory
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
70, you use the Beam-provided
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 transform. Apply this transform directly to your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 object itself

To create a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 from an in-memory
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
74, you use the Beam-provided
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
75 transform. Pass the pipeline
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
76, and the
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
74 to this transform

To create a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 from an in-memory
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
79, you use the Beam-provided
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 transform. Apply this transform directly to your
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
81 object

Mã ví dụ sau đây cho biết cách tạo

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 từ bộ nhớ trong
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
83
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
70
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
74 .
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
79
:

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
1

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
2

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
3

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
4

3. 2. Đặc tính bộ sưu tập

A

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 được sở hữu bởi đối tượng cụ thể
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 mà nó được tạo ra; . Ở một số khía cạnh, một lớp
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 giống như một lớp
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
59. Tuy nhiên, một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có thể khác nhau theo một số cách chính.

3. 2. 1. Loại nguyên tố

Các phần tử của một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có thể thuộc bất kỳ loại nào, nhưng tất cả phải cùng loại. Tuy nhiên, để hỗ trợ xử lý phân tán, Beam cần có khả năng mã hóa từng phần tử riêng lẻ dưới dạng chuỗi byte [để các phần tử có thể được chuyển cho các công nhân phân tán]. Beam SDK cung cấp cơ chế mã hóa dữ liệu bao gồm mã hóa tích hợp cho các loại thường được sử dụng cũng như hỗ trợ chỉ định mã hóa tùy chỉnh khi cần

3. 2. 2. lược đồ phần tử

Trong nhiều trường hợp, loại phần tử trong

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có cấu trúc có thể xem xét nội tâm. Ví dụ là các bản ghi JSON, Bộ đệm giao thức, Avro và cơ sở dữ liệu. Các lược đồ cung cấp một cách để thể hiện các loại dưới dạng một tập hợp các trường được đặt tên, cho phép các tập hợp biểu cảm hơn

3. 2. 3. tính bất biến

Một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là bất biến. Sau khi tạo, bạn không thể thêm, xóa hoặc thay đổi các thành phần riêng lẻ. Chuyển đổi Beam có thể xử lý từng phần tử của
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 và tạo dữ liệu đường ống mới [dưới dạng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 mới], nhưng nó không sử dụng hoặc sửa đổi bộ sưu tập đầu vào ban đầu

Ghi chú. Beam SDK tránh việc sao chép các thành phần không cần thiết, vì vậy nội dung của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là bất biến về mặt logic chứ không phải bất biến về mặt vật lý. Các thay đổi đối với các thành phần đầu vào có thể hiển thị đối với các DoFns khác đang thực thi trong cùng một gói và có thể gây ra các vấn đề về tính chính xác. Theo quy định, sẽ không an toàn khi sửa đổi các giá trị được cung cấp cho DoFn

3. 2. 4. Truy cập ngẫu nhiên

Một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không hỗ trợ truy cập ngẫu nhiên vào các phần tử riêng lẻ. Thay vào đó, Beam Transforms xem xét từng phần tử trong một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 riêng lẻ

3. 2. 5. Kích thước và giới hạn

Một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là một “túi” phần tử lớn, bất biến. Không có giới hạn trên về số lượng phần tử mà một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có thể chứa;

Một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có thể có kích thước giới hạn hoặc không giới hạn. Một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn biểu thị một tập dữ liệu có kích thước cố định, đã biết, trong khi một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn biểu thị một tập dữ liệu có kích thước không giới hạn. Việc một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn hay không giới hạn phụ thuộc vào nguồn của tập dữ liệu mà nó đại diện. Việc đọc từ nguồn dữ liệu lô, chẳng hạn như tệp hoặc cơ sở dữ liệu, sẽ tạo ra một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn. Việc đọc từ nguồn dữ liệu phát trực tuyến hoặc cập nhật liên tục, chẳng hạn như Pub/Sub hoặc Kafka, sẽ tạo ra một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn [trừ khi bạn yêu cầu rõ ràng là không làm như vậy]

Bản chất bị chặn [hoặc không bị chặn] của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn ảnh hưởng đến cách Beam xử lý dữ liệu của bạn. Có thể xử lý một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn bằng cách sử dụng một công việc hàng loạt, công việc này có thể đọc toàn bộ tập dữ liệu một lần và thực hiện xử lý trong một công việc có độ dài hữu hạn. Một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn phải được xử lý bằng cách sử dụng công việc phát trực tuyến chạy liên tục, vì toàn bộ bộ sưu tập không bao giờ có sẵn để xử lý cùng một lúc

Beam sử dụng để chia một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 cập nhật liên tục thành các cửa sổ logic có kích thước hữu hạn. Các cửa sổ logic này được xác định bởi một số đặc điểm được liên kết với một phần tử dữ liệu, chẳng hạn như dấu thời gian. Các phép biến đổi tổng hợp [chẳng hạn như
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 và
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15] hoạt động trên cơ sở mỗi cửa sổ — khi tập dữ liệu được tạo, chúng xử lý từng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 dưới dạng chuỗi liên tiếp của các cửa sổ hữu hạn này

3. 2. 6. dấu thời gian phần tử

Mỗi phần tử trong

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có dấu thời gian nội tại được liên kết. Dấu thời gian cho mỗi phần tử ban đầu được chỉ định bởi phần tử tạo ra
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Các nguồn tạo
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn thường gán cho mỗi phần tử mới một dấu thời gian tương ứng với thời điểm phần tử được đọc hoặc thêm vào

Ghi chú. Các nguồn tạo ra một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn cho một tập dữ liệu cố định cũng tự động gán dấu thời gian, nhưng hành vi phổ biến nhất là gán cho mọi phần tử cùng một dấu thời gian [
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
21]

Dấu thời gian rất hữu ích cho một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 chứa các phần tử có khái niệm cố hữu về thời gian. Nếu quy trình bán hàng của bạn đang đọc một luồng sự kiện, chẳng hạn như Tweet hoặc các thông báo trên mạng xã hội khác, thì mỗi phần tử có thể sử dụng thời gian sự kiện được đăng làm dấu thời gian của phần tử

Bạn có thể tự gán dấu thời gian cho các thành phần của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 nếu nguồn không làm việc đó cho bạn. Bạn sẽ muốn làm điều này nếu các phần tử có dấu thời gian vốn có, nhưng dấu thời gian nằm ở đâu đó trong cấu trúc của chính phần tử đó [chẳng hạn như trường “thời gian” trong mục nhập nhật ký máy chủ]. Beam có một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 làm đầu vào và đầu ra là một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 giống hệt nhau với các dấu thời gian được đính kèm;

4. Transforms

Transforms are the operations in your pipeline, and provide a generic processing framework. You provide processing logic in the form of a function object [colloquially referred to as “user code”], and your user code is applied to each element of an input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [or more than one
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73]. Depending on the pipeline runner and back-end that you choose, many different workers across a cluster may execute instances of your user code in parallel. The user code running on each worker generates the output elements that are ultimately added to the final output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that the transform produces

Aggregation is an important concept to understand when learning about Beam’s transforms. For an introduction to aggregation, see the Basics of the Beam model

The Beam SDKs contain a number of different transforms that you can apply to your pipeline’s

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. These include general-purpose core transforms, such as or . There are also pre-written included in the SDKs, which combine one or more of the core transforms in a useful processing pattern, such as counting or combining elements in a collection. You can also define your own more complex composite transforms to fit your pipeline’s exact use case

4. 1. Applying transforms

To invoke a transform, you must apply it to the input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Each transform in the Beam SDKs has a generic
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31 method [or pipe operator
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
32]
. Invoking multiple Beam transforms is similar to method chaining, but with one slight difference. You apply the transform to the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, passing the transform itself as an argument, and the operation returns the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. This takes the general form.

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
5

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
6

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
7

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
8

Bởi vì Beam sử dụng một phương pháp chung

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31 cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, nên bạn có thể thực hiện cả hai phép biến đổi chuỗi một cách tuần tự và cũng có thể áp dụng các phép biến đổi có chứa các biến đổi khác được lồng vào bên trong [được gọi trong Beam SDK]

It’s recommended to create a new variable for each new

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to sequentially transform input data.
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
84s can be used to create functions that contain other transforms [called in the Beam SDKs]

How you apply your pipeline’s transforms determines the structure of your pipeline. The best way to think of your pipeline is as a directed acyclic graph, where

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 nodes are subroutines that accept
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 nodes as inputs and emit
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 nodes as outputs. For example, you can chain together transforms to create a pipeline that successively modifies input data. For example, you can successively call transforms on PCollections to modify the input data.

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
9

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
0

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
1

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
2

The graph of this pipeline looks like the following

Figure 1. A linear pipeline with three sequential transforms

However, note that a transform does not consume or otherwise alter the input collection — remember that a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 is immutable by definition. This means that you can apply multiple transforms to the same input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to create a branching pipeline, like so

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
3

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
4

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
5

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
6

The graph of this branching pipeline looks like the following

Figure 2. A branching pipeline. Two transforms are applied to a single PCollection of database table rows

You can also build your own that nest multiple transforms inside a single, larger transform. Composite transforms are particularly useful for building a reusable sequence of simple steps that get used in a lot of different places

The pipe syntax allows one to apply PTransforms to

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
44s and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
45s of PCollections as well for those transforms accepting multiple inputs [such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47]

PTransforms can also be applied to any

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
48, which include the Root object, PCollections, arrays of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
48s, and objects with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
48 values. One can apply transforms to these composite types by wrapping them with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
51, e. g.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
52

PTransforms come in two flavors, synchronous and asynchronous, depending on whether their application* involves asynchronous invocations. An

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
53 must be applied with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
54 and returns a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
55 which must be awaited before further pipeline construction

4. 2. Core Beam transforms

Beam provides the following core transforms, each of which represents a different processing paradigm

  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    14
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    47
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    15
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    46
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    61

The Typescript SDK provides some of the most basic of these transforms as methods on

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 itself

4. 2. 1. ParDo

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 is a Beam transform for generic parallel processing. The
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 processing paradigm is similar to the “Map” phase of a Map/Shuffle/Reduce-style algorithm. a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform considers each element in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, performs some processing function [your user code] on that element, and emits zero, one, or multiple elements to an output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 is useful for a variety of common data processing operations, including

  • Filtering a data set. You can use
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 to consider each element in a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 and either output that element to a new collection or discard it
  • Formatting or type-converting each element in a data set. If your input
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 contains elements that are of a different type or format than you want, you can use
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 to perform a conversion on each element and output the result to a new
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73
  • Extracting parts of each element in a data set. If you have a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of records with multiple fields, for example, you can use a
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 to parse out just the fields you want to consider into a new
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73
  • Performing computations on each element in a data set. You can use
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 to perform simple or complex computations on every element, or certain elements, of a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 and output the results as a new
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73

In such roles,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 is a common intermediate step in a pipeline. Bạn có thể sử dụng nó để trích xuất các trường nhất định từ một tập hợp các bản ghi đầu vào thô hoặc chuyển đổi đầu vào thô sang một định dạng khác;

When you apply a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform, you’ll need to provide user code in the form of a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 object.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 is a Beam SDK class that defines a distributed processing function

When you create a subclass of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83, note that your subclass should adhere to the

All DoFns should be registered using a generic

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
86 function. This allows the Go SDK to infer an encoding from any inputs/outputs, registers the DoFn for execution on remote runners, and optimizes the runtime execution of the DoFns via reflection

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
7

4. 2. 1. 1. Applying ParDo

Like all Beam transforms, you apply

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 by calling the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31 method on the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 and passing
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 as an argument, as shown in the following example code

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
91 applies the passed in
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 argument to the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, as shown in the following example code

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
8

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
9

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
0

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
1

In the example, our input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 contains
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96
values. We apply a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform that specifies a function [
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
98] to compute the length of each string, and outputs the result to a new
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
00
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01
values that stores the length of each word.

4. 2. 1. 2. Creating a DoFn

The

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 object that you pass to
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 contains the processing logic that gets applied to the elements in the input collection. When you use Beam, often the most important pieces of code you’ll write are these
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83s - they’re what define your pipeline’s exact data processing tasks

Note. Khi bạn tạo

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 của mình, hãy lưu ý và đảm bảo rằng mã của bạn tuân theo chúng

A

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 processes one element at a time from the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. When you create a subclass of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83, you’ll need to provide type parameters that match the types of the input and output elements. If your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 processes incoming
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50 elements and produces
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
00 elements for the output collection [like our previous example,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
98], your class declaration would look like this

A

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 processes one element at a time from the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. When you create a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 struct, you’ll need to provide type parameters that match the types of the input and output elements in a ProcessElement method. Nếu
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 của bạn xử lý các phần tử
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96 đến và tạo ra các phần tử
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01 cho tập hợp đầu ra [như ví dụ trước của chúng tôi,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
98], dofn của bạn có thể trông như thế này

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
2

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
3

Inside your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 subclass, you’ll write a method annotated with
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 where you provide the actual processing logic. Bạn không cần trích xuất thủ công các phần tử từ bộ sưu tập đầu vào; . Phương thức
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 của bạn phải chấp nhận tham số được gắn thẻ
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
23, tham số này sẽ được điền bằng phần tử đầu vào. Để xuất các phần tử, phương thức cũng có thể nhận một tham số kiểu
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
24 cung cấp một phương thức để xuất các phần tử. The parameter types must match the input and output types of your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 or the framework will raise an error. Note.
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
23 and
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
24 were introduced in Beam 2. 5. 0; if using an earlier release of Beam, a
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
28 parameter should be used instead

Inside your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 subclass, you’ll write a method
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 where you provide the actual processing logic. You don’t need to manually extract the elements from the input collection; the Beam SDKs handle that for you. Your
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method should accept an argument
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
32, which is the input element, and return an iterable with its output values. You can accomplish this by emitting individual elements with
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
33 statements. You can also use a
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
34 statement with an iterable, like a list or a generator. Don’t mix
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
33 and
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
34 statements in the same
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method - this leads to undefined behavior

For your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 type, you’ll write a method
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
39 where you provide the actual processing logic. You don’t need to manually extract the elements from the input collection; the Beam SDKs handle that for you. Your
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
39 method should accept a parameter
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
32, which is the input element. In order to output elements, the method can also take a function parameter, which can be called to emit elements. The parameter types must match the input and output types of your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 or the framework will raise an error

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
4

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
5

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
6

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
7

Simple DoFns can also be written as functions

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
8

Ghi chú. Whether using a structural

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 type or a functional
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83, they should be registered with beam in an
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
45 block. Otherwise they may not execute on distributed runners.

Ghi chú. Nếu các thành phần trong dữ liệu đầu vào của bạn

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là các cặp khóa/giá trị, thì bạn có thể truy cập khóa hoặc giá trị bằng cách sử dụng lần lượt là
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
47 hoặc
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
48.

Ghi chú. Nếu các phần tử trong đầu vào của bạn

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là các cặp khóa/giá trị, thì phương thức phần tử quy trình của bạn phải có hai tham số, tương ứng cho mỗi khóa và giá trị. Tương tự, các cặp khóa/giá trị cũng được xuất dưới dạng các tham số riêng biệt cho một
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
50

A given

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 instance generally gets invoked one or more times to process some arbitrary bundle of elements. However, Beam doesn’t guarantee an exact number of invocations; it may be invoked multiple times on a given worker node to account for failures and retries. As such, you can cache information across multiple calls to your processing method, but if you do so, make sure the implementation does not depend on the number of invocations

In your processing method, you’ll also need to meet some immutability requirements to ensure that Beam and the processing back-end can safely serialize and cache the values in your pipeline. Your method should meet the following requirements

  • You should not in any way modify an element returned by the
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    23 annotation or
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    53 [the incoming elements from the input collection].
  • Once you output a value using
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    54 you should not modify that value in any way
  • You should not in any way modify the
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    32 argument provided to the
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    30 method, or any side inputs.
  • Once you output a value using
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    33 or
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    34, you should not modify that value in any way
  • Bạn không nên sửa đổi các tham số được cung cấp cho phương thức
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    39 hoặc bất kỳ đầu vào phụ nào theo bất kỳ cách nào.
  • Once you output a value using an
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    50, you should not modify that value in any way
4. 2. 1. 3. Lightweight DoFns and other abstractions

If your function is relatively straightforward, you can simplify your use of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 by providing a lightweight
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 in-line, as an anonymous inner class instance a lambda function an anonymous function a function passed to
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
63 or
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
64
.

Here’s the previous example,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 with
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
66, with the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 specified as an anonymous inner class instance a lambda function an anonymous function a function .

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
9

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
0

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
1

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
2

If your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 performs a one-to-one mapping of input elements to output elements–that is, for each input element, it applies a function that produces exactly one output element, you can return that element directly. you can use the higher-level
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
69
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
70
transform.
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
69 can accept an anonymous Java 8 lambda function for additional brevity.

Here’s the previous example using

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
69
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
70
a direct return .

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
3

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
4

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
5

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
6

Note. You can use Java 8 lambda functions with several other Beam transforms, including

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
74,
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
75, and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61.

Ghi chú. Chức năng ẩn danh DoFns có thể không hoạt động trên các trình chạy phân tán. Bạn nên sử dụng các hàm được đặt tên và đăng ký chúng với

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
77 trong một khối
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
78

4. 2. 1. 4. DoFn lifecycle

Here is a sequence diagram that shows the lifecycle of the DoFn during the execution of the ParDo transform. The comments give useful information to pipeline developers such as the constraints that apply to the objects or particular cases such as failover or instance reuse. They also give instantiation use cases

4. 2. 2. GroupByKey

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 is a Beam transform for processing collections of key/value pairs. It’s a parallel reduction operation, analogous to the Shuffle phase of a Map/Shuffle/Reduce-style algorithm. The input to
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 is a collection of key/value pairs that represents a multimap, where the collection contains multiple pairs that have the same key, but different values. Given such a collection, you use
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 to collect all of the values associated with each unique key

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 là một cách hay để tổng hợp dữ liệu có điểm chung. For example, if you have a collection that stores records of customer orders, you might want to group together all the orders from the same postal code [wherein the “key” of the key/value pair is the postal code field, and the “value” is the remainder of the record]

Let’s examine the mechanics of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 with a simple example case, where our data set consists of words from a text file and the line number on which they appear. We want to group together all the line numbers [values] that share the same word [key], letting us see all the places in the text where a particular word appears

Our input is a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of key/value pairs where each word is a key, and the value is a line number in the file where the word appears. Here’s a list of the key/value pairs in the input collection

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
7

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 gathers up all the values with the same key and outputs a new pair consisting of the unique key and a collection of all of the values that were associated with that key in the input collection. If we apply
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 to our input collection above, the output collection would look like this

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
8

Thus,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 represents a transform from a multimap [multiple keys to individual values] to a uni-map [unique keys to collections of values]

Using

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 is straightforward

While all SDKs have a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 transform, using
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
90 is generally more natural. The
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
90 transform can be parameterized by the name[s] of properties on which to group the elements of the PCollection, or a function taking the each element as input that maps to a key on which to do grouping

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
9

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
0

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
1

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
2

4. 2. 2. 1 GroupByKey and unbounded PCollections

If you are using unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, you must use either or an in order to perform a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or . This is because a bounded
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 must wait for all the data with a certain key to be collected, but with unbounded collections, the data is unlimited. Cửa sổ và/hoặc trình kích hoạt cho phép nhóm hoạt động trên các gói dữ liệu logic, hữu hạn trong các luồng dữ liệu không giới hạn

If you do apply

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 to a group of unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s without setting either a non-global windowing strategy, a trigger strategy, or both for each collection, Beam generates an IllegalStateException error at pipeline construction time

When using

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 to group
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s that have a applied, all of the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s you want to group must use the same windowing strategy and window sizing. For example, all of the collections you are merging must use [hypothetically] identical 5-minute fixed windows, or 4-minute sliding windows starting every 30 seconds

If your pipeline attempts to use

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 to merge
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s with incompatible windows, Beam generates an IllegalStateException error at pipeline construction time

4. 2. 3. CoGroupByKey

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 performs a relational join of two or more key/value
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s that have the same key type. shows an example pipeline that uses a join

Consider using

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 if you have multiple data sets that provide information about related things. Ví dụ: giả sử bạn có hai tệp khác nhau chứa dữ liệu người dùng. one file has names and email addresses; the other file has names and phone numbers. You can join those two data sets, using the user name as a common key and the other data as the associated values. After the join, you have one data set that contains all of the information [email addresses and phone numbers] associated with each name

If you are using unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, you must use either or an in order to perform a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47. See for more details

In the Beam SDK for Java,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 accepts a tuple of keyed
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s [
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
13] as input. For type safety, the SDK requires you to pass each
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as part of a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
15. You must declare a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
16 for each input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 in the
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
15 that you want to pass to
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47. As output,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 returns a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
21, which groups values from all the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s by their common keys. Each key [all of type
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
23] will have a different
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
24, which is a map from
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
25 to
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
26. You can access a specific collection in an
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
24 object by using the
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
16 that you supplied with the initial collection

In the Beam SDK for Python,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 accepts a dictionary of keyed
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as input. As output,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 creates a single output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that contains one key/value tuple for each key in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. Each key’s value is a dictionary that maps each tag to an iterable of the values under they key in the corresponding
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

In the Beam Go SDK,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 accepts an arbitrary number of
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as input. As output,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 creates a single output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that groups each key with value iterator functions for each input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The iterator functions map to input
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
40 in the same order they were provided to the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47

Các ví dụ khái niệm sau đây sử dụng hai tập hợp đầu vào để hiển thị cơ chế của

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47

The first set of data has a

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
43 called
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
44 and contains names and email addresses. The second set of data has a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
43 called
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
46 and contains names and phone numbers

The first set of data contains names and email addresses. The second set of data contains names and phone numbers

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
3

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
4

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
5

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
6

After

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47, the resulting data contains all data associated with each unique key from any of the input collections

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
7

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
8

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
9

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
0

The following code example joins the two

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47, followed by a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 to consume the result. Then, the code uses tags to look up and format data from each collection

The following code example joins the two

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47, followed by a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 to consume the result. The ordering of the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 iterator parameters maps to the ordering of the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 inputs

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
1

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
2

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
3

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
4

The formatted data looks like this

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
5

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
6

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
7

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
8

4. 2. 4. Combine

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15
is a Beam transform for combining collections of elements or values in your data.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 has variants that work on entire
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, and some that combine the values for each key in
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s of key/value pairs.

When you apply a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 transform, you must provide the function that contains the logic for combining the elements or values. The combining function should be commutative and associative, as the function is not necessarily invoked exactly once on all values with a given key. Because the input data [including the value collection] may be distributed across multiple workers, the combining function might be called multiple times to perform partial combining on subsets of the value collection. The Beam SDK also provides some pre-built combine functions for common numeric combination operations such as sum, min, and max

Simple combine operations, such as sums, can usually be implemented as a simple function. More complex combination operations might require you to create a subclass of

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64 that has an accumulation type distinct from the input/output type.

The associativity and commutativity of a

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64 allows runners to automatically apply some optimizations

  • Combiner lifting. This is the most significant optimization. Input elements are combined per key and window before they are shuffled, so the volume of data shuffled might be reduced by many orders of magnitude. Another term for this optimization is “mapper-side combine. ”
  • Incremental combining. When you have a
    const pipeline_options = {
      runner: "default",
      project: "my_project",
    };
    
    const runner = beam.createRunner[pipeline_options];
    
    const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
    
    64 that reduces the data size by a lot, it is useful to combine elements as they emerge from a streaming shuffle. This spreads out the cost of doing combines over the time that your streaming computation might be idle. Incremental combining also reduces the storage of intermediate accumulators
4. 2. 4. 1. Simple combinations using simple functions

The following example code shows a simple combine function. Combining is done by modifying a grouping transform with the

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
67 method. This method takes three parameters. the value to combine [either as a named property of the input elements, or a function of the entire input], the combining operation [either a binary function or a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64], and finally a name for the combined value in the output object.

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
9

--=
0

--=
1

--=
2

All Combiners should be registered using a generic

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
69 function. This allows the Go SDK to infer an encoding from any inputs/outputs, registers the Combiner for execution on remote runners, and optimizes the runtime execution of the Combiner via reflection

Combiner1 should be used when your accumulator, input, and output are all of the same type. It can be called with

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
70 where
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
71 is the type of the input/accumulator/output

Combiner2 should be used when your accumulator, input, and output are 2 distinct types. It can be called with

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
72 where
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
73 is the type of the accumulator and
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
74 is the other type

Combiner3 should be used when your accumulator, input, and output are 3 distinct types. It can be called with

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
75 where
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
73 is the type of the accumulator,
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
74 is the type of the input, and
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
78 is the type of the output

4. 2. 4. 2. Advanced combinations using CombineFn

For more complex combine functions, you can define a subclass of

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64. You should use a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64 if the combine function requires a more sophisticated accumulator, must perform additional pre- or post-processing, might change the output type, or takes the key into account.

A general combining operation consists of four operations. When you create a subclass of

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64, you must provide four operations by overriding the corresponding methods.

  1. Create Accumulator creates a new “local” accumulator. In the example case, taking a mean average, a local accumulator tracks the running sum of values [the numerator value for our final average division] and the number of values summed so far [the denominator value]. It may be called any number of times in a distributed fashion

  2. Add Input adds an input element to an accumulator, returning the accumulator value. In our example, it would update the sum and increment the count. It may also be invoked in parallel

  3. Merge Accumulators merges several accumulators into a single accumulator; this is how data in multiple accumulators is combined before the final calculation. In the case of the mean average computation, the accumulators representing each portion of the division are merged together. It may be called again on its outputs any number of times

  4. Trích xuất đầu ra thực hiện tính toán cuối cùng. In the case of computing a mean average, this means dividing the combined sum of all the values by the number of values summed. Nó được gọi một lần trên bộ tích lũy cuối cùng, được hợp nhất

The following example code shows how to define a

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64 that computes a mean average

--=
3

--=
4

--=
5

--=
6

Note. Only

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
83 is a required method. The others will have a default interpretation based on the accumulator type

4. 2. 4. 3. Combining a PCollection into a single value

Use the global combine to transform all of the elements in a given

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into a single value, represented in your pipeline as a new
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 containing one element. The following example code shows how to apply the Beam provided sum combine function to produce a single sum value for a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of integers

--=
7

--=
8

--=
9

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
0

4. 2. 4. 4. Combine and global windowing

If your input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 uses the default global windowing, the default behavior is to return a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 containing one item. That item’s value comes from the accumulator in the combine function that you specified when applying
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15. For example, the Beam provided sum combine function returns a zero value [the sum of an empty input], while the min combine function returns a maximal or infinite value

To have

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 instead return an empty
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 if the input is empty, specify
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
92 when you apply your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 transform, as in the following code example

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
1

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
2

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
3

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
4

4. 2. 4. 5. Combine and non-global windowing

If your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 uses any non-global windowing function, Beam does not provide the default behavior. You must specify one of the following options when applying
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15

  • Chỉ định
    const pipeline_options = {
      runner: "default",
      project: "my_project",
    };
    
    const runner = beam.createRunner[pipeline_options];
    
    const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
    
    92, trong đó các cửa sổ trống trong đầu vào
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 cũng sẽ trống trong bộ sưu tập đầu ra
  • Specify
    const pipeline_options = {
      runner: "default",
      project: "my_project",
    };
    
    const runner = beam.createRunner[pipeline_options];
    
    const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
    
    98, in which the output is immediately converted to a
    const pipeline_options = {
      runner: "default",
      project: "my_project",
    };
    
    const runner = beam.createRunner[pipeline_options];
    
    const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
    
    99, which will provide a default value for each empty window when used as a side input. You’ll generally only need to use this option if the result of your pipeline’s
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    15 is to be used as a side input later in the pipeline

If your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 uses any non-global windowing function, the Beam Go SDK behaves the same way as with global windowing. Windows that are empty in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 will likewise be empty in the output collection

4. 2. 4. 6. Combining values in a keyed PCollection

After creating a keyed PCollection [for example, by using a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 transform], a common pattern is to combine the collection of values associated with each key into a single, merged value. Drawing on the previous example from
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14, a key-grouped
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 called
--=
06 looks like this

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
5

In the above

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, each element has a string key [for example, “cat”] and an iterable of integers for its value [in the first element, containing [1, 5, 9]]. If our pipeline’s next processing step combines the values [rather than considering them individually], you can combine the iterable of integers to create a single, merged value to be paired with each key. This pattern of a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 followed by merging the collection of values is equivalent to Beam’s Combine PerKey transform. The combine function you supply to Combine PerKey must be an associative reduction function or a subclass of
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64.

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
6

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
7

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
8

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
9

4. 2. 5. Flatten

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46
is a Beam transform for
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects that store the same data type.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 merges multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects into a single logical
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73.

The following example shows how to apply a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 transform to merge multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
00

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
01

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
02

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
03

4. 2. 5. 1. Data encoding in merged collections

By default, the coder for the output

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 is the same as the coder for the first
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 in the input
--=
22. However, the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects can each use different coders, as long as they all contain the same data type in your chosen language

4. 2. 5. 2. Merging windowed collections

When using

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 to merge
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects that have a windowing strategy applied, all of the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects you want to merge must use a compatible windowing strategy and window sizing. For example, all the collections you’re merging must all use [hypothetically] identical 5-minute fixed windows or 4-minute sliding windows starting every 30 seconds

If your pipeline attempts to use

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 to merge
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects with incompatible windows, Beam generates an
--=
29 error when your pipeline is constructed

4. 2. 6. Partition

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61
is a Beam transform for
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects that store the same data type.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61 splits a single
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into a fixed number of smaller collections.

Often in the Typescript SDK the

--=
37 transform is more natural to use

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61 divides the elements of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 according to a partitioning function that you provide. The partitioning function contains the logic that determines how to split up the elements of the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into each resulting partition
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The number of partitions must be determined at graph construction time. You can, for example, pass the number of partitions as a command-line option at runtime [which will then be used to build your pipeline graph], but you cannot determine the number of partitions in mid-pipeline [based on data calculated after your pipeline graph is constructed, for instance]

The following example divides a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into percentile groups

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
04

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
05

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
06

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
07

4. 3. Requirements for writing user code for Beam transforms

When you build user code for a Beam transform, you should keep in mind the distributed nature of execution. For example, there might be many copies of your function running on a lot of different machines in parallel, and those copies function independently, without communicating or sharing state with any of the other copies. Tùy thuộc vào Trình chạy đường ống và xử lý back-end mà bạn chọn cho đường ống của mình, mỗi bản sao chức năng mã người dùng của bạn có thể được thử lại hoặc chạy nhiều lần. As such, you should be cautious about including things like state dependency in your user code

In general, your user code must fulfill at least these requirements

  • Your function object must be serializable
  • Your function object must be thread-compatible, and be aware that the Beam SDKs are not thread-safe

In addition, it’s recommended that you make your function object idempotent. Non-idempotent functions are supported by Beam, but require additional thought to ensure correctness when there are external side effects

Note. These requirements apply to subclasses of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83[a function object used with the transform],
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64 [a function object used with the transform], and
--=
45 [a function object used with the transform].

Ghi chú. Những yêu cầu này áp dụng cho

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83s [một đối tượng hàm được sử dụng với biến đổi],
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64s [một đối tượng hàm được sử dụng với biến đổi] và
--=
45s [một đối tượng hàm được sử dụng với biến đổi]

4. 3. 1. Serializability

Any function object you provide to a transform must be fully serializable. This is because a copy of the function needs to be serialized and transmitted to a remote worker in your processing cluster. The base classes for user code, such as

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83,
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64, and
--=
45, already implement
--=
52; however, your subclass must not add any non-serializable members. Funcs are serializable as long as they are registered with
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
77 [for simple functions] or
--=
54 [for structural DoFns], and are not closures. Structural
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83s will have all exported fields serialized. Unexported fields are unable to be serialized, and will be silently ignored.
The Typescript SDK use ts-serialize-closures to serialize functions [and other objects]. This works out of the box for functions that are not closures, and also works for closures as long as the function in question [and any closures it references] are compiled with the
--=
56 hooks [e. g. by using
--=
57 in place of
--=
58]. One can alternatively call
--=
59 to register a function directly by name which can be less error-prone. Note that if, as is often the case in Javascript,
--=
60 returns objects that contain closures, it is not sufficient to register
--=
60 alone–its return value must be registered if used.

Some other serializability factors you should keep in mind are

  • TransientUnexported fields in your function object are not transmitted to worker instances, because they are not automatically serialized.
  • Tránh tải một trường có lượng dữ liệu lớn trước khi tuần tự hóa
  • Các phiên bản riêng lẻ của đối tượng chức năng của bạn không thể chia sẻ dữ liệu
  • Mutating a function object after it gets applied will have no effect

Note. Take care when declaring your function object inline by using an anonymous inner class instance. In a non-static context, your inner class instance will implicitly contain a pointer to the enclosing class and that class’ state. That enclosing class will also be serialized, and thus the same considerations that apply to the function object itself also apply to this outer class.

Ghi chú. Không có cách nào để phát hiện xem một chức năng có phải là một bao đóng hay không. Việc đóng cửa sẽ gây ra lỗi thời gian chạy và lỗi đường ống. Tránh sử dụng các chức năng ẩn danh khi có thể

4. 3. 2. Khả năng tương thích chủ đề

Đối tượng chức năng của bạn phải tương thích với luồng. Each instance of your function object is accessed by a single thread at a time on a worker instance, unless you explicitly create your own threads. Note, however, that the Beam SDKs are not thread-safe. If you create your own threads in your user code, you must provide your own synchronization. Note that static members in your function object are not passed to worker instances and that multiple instances of your function may be accessed from different threads.

4. 3. 3. Idempotence

It’s recommended that you make your function object idempotent–that is, that it can be repeated or retried as often as necessary without causing unintended side effects. Non-idempotent functions are supported, however the Beam model provides no guarantees as to the number of times your user code might be invoked or retried; as such, keeping your function object idempotent keeps your pipeline’s output deterministic, and your transforms’ behavior more predictable and easier to debug

4. 4. Side inputs

In addition to the main input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, you can provide additional inputs to a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform in the form of side inputs. A side input is an additional input that your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 can access each time it processes an element in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. When you specify a side input, you create a view of some other data that can be read from within the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform’s
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 while processing each element

Side inputs are useful if your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 needs to inject additional data when processing each element in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, but the additional data needs to be determined at runtime [and not hard-coded]. Các giá trị như vậy có thể được xác định bởi dữ liệu đầu vào hoặc phụ thuộc vào một nhánh khác trong quy trình của bạn

All side input iterables should be registered using a generic

--=
70 function. This optimizes runtime execution of the iterable

4. 4. 1. Passing side inputs to ParDo

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
08

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
09

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
10

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
11

4. 4. 2. Side inputs and windowing

A windowed

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 may be infinite and thus cannot be compressed into a single value [or single collection class]. When you create a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
99 of a windowed
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, the
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
99 represents a single entity per window [one singleton per window, one list per window, etc. ]

Beam uses the window[s] for the main input element to look up the appropriate window for the side input element. Beam projects the main input element’s window into the side input’s window set, and then uses the side input from the resulting window. If the main input and side inputs have identical windows, the projection provides the exact corresponding window. However, if the inputs have different windows, Beam uses the projection to choose the most appropriate side input window

For example, if the main input is windowed using fixed-time windows of one minute, and the side input is windowed using fixed-time windows of one hour, Beam projects the main input window against the side input window set and selects the side input value from the appropriate hour-long side input window

If the main input element exists in more than one window, then

--=
75 gets called multiple times, once for each window. Each call to
--=
75 projects the “current” window for the main input element, and thus might provide a different view of the side input each time

If the side input has multiple trigger firings, Beam uses the value from the latest trigger firing. This is particularly useful if you use a side input with a single global window and specify a trigger

4. 5. Additional outputs

While

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 always produces a main output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [as the return value from
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31], you can also have your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 produce any number of additional output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. If you choose to have multiple outputs, your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 returns all of the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s [including the main output] bundled together

While

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
91 always produces an output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 can produce any number of additional output
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
40s, or even none at all. If you choose to have multiple outputs, your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 needs to be called with the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 function that matches the number of outputs.
--=
90 for two output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s,
--=
92 for three and so on until
--=
93. If you need more, you can use
--=
94 which will return a
--=
95

While

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 always produces a main output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [as the return value from
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31]. If you want to have multiple outputs, emit an object with distinct properties in your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 operation and follow this operation with a
--=
37 to break it into multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s

4. 5. 1. Tags for multiple outputs

The

--=
37 PTransform will take a PCollection of elements of the form
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
03 and return a object
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
04. The set of expected tags is passed to the operation; how multiple or unknown tags are handled can be specified by passing a non-default
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
05 instance

The Go SDK doesn’t use output tags, and instead uses positional ordering for multiple output PCollections

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
12

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
13

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
14

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
15

4. 5. 2. Emitting to multiple outputs in your DoFn

Call emitter functions as needed to produce 0 or more elements for its matching

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The same value can be emitted with multiple emitters. As normal, do not mutate values after emitting them from any emitter

All emitters should be registered using a generic

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
07 function. This optimizes runtime execution of the emitter

DoFns can also return a single element via the standard return. The standard return is always the first PCollection returned from beam. ParDo. Other emitters output to their own PCollections in their defined parameter order

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
16

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
17

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
18

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
19

4. 5. 3. Accessing additional parameters in your DoFn

In addition to the element and the

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
24, Beam will populate other parameters to your DoFn’s
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 method. Bất kỳ sự kết hợp nào của các tham số này đều có thể được thêm vào phương thức quy trình của bạn theo bất kỳ thứ tự nào

In addition to the element, Beam will populate other parameters to your DoFn’s

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method. Any combination of these parameters can be added to your process method in any order

In addition to the element, Beam will populate other parameters to your DoFn’s

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method. These are available by placing accessors in the context argument, just as for side inputs

In addition to the element, Beam will populate other parameters to your DoFn’s

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
39 method. Any combination of these parameters can be added to your process method in a standard order

context. Context. To support consolidated logging and user defined metrics, a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
13 parameter can be requested. Per Go conventions, if present it’s required to be the first parameter of the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 method

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
20

Timestamp. To access the timestamp of an input element, add a parameter annotated with

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
15 of type
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
16. For example

Timestamp. To access the timestamp of an input element, add a keyword parameter default to

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
17. For example

Timestamp. To access the timestamp of an input element, add a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
18 parameter before the element. For example

Timestamp. To access the window an input element falls into, add a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
19 to the context argument

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
21

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
22

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
23

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
24

Window. To access the window an input element falls into, add a parameter of the type of the window used for the input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. If the parameter is a window type [a subclass of
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
21] that does not match the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, then an error will be raised. If an element falls in multiple windows [for example, this will happen when using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
23], then the
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 method will be invoked multiple time for the element, once for each window. For example, when fixed windows are being used, the window is of type
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
25

Window. To access the window an input element falls into, add a keyword parameter default to

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
26. If an element falls in multiple windows [for example, this will happen when using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
23], then the
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method will be invoked multiple time for the element, once for each window

Window. Để truy cập vào cửa sổ có phần tử đầu vào, hãy thêm tham số

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
29 trước phần tử. If an element falls in multiple windows [for example, this will happen when using SlidingWindows], then the
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
39 method will be invoked multiple time for the element, once for each window. Since
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
29 is an interface it’s possible to type assert to the concrete implementation of the window. For example, when fixed windows are being used, the window is of type
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
32

Window. To access the window an input element falls into, add a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
19 to the context argument. If an element falls in multiple windows [for example, this will happen when using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
23], then the function will be invoked multiple time for the element, once for each window

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
25

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
26

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
27

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
28

PaneInfo. When triggers are used, Beam provides a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
35 object that contains information about the current firing. Using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
35 you can determine whether this is an early or a late firing, and how many times this window has already fired for this key

PaneInfo. When triggers are used, Beam provides a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
37 object that contains information about the current firing. Using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
37 you can determine whether this is an early or a late firing, and how many times this window has already fired for this key. This feature implementation in Python SDK is not fully completed; see more at Issue 17821

PaneInfo. When triggers are used, Beam provides

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
39 object that contains information about the current firing. Sử dụng
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
39, bạn có thể xác định xem đây là lần kích hoạt sớm hay muộn và cửa sổ này đã kích hoạt bao nhiêu lần cho khóa này

Window. Để truy cập vào cửa sổ có phần tử đầu vào, hãy thêm ____64_______41 vào đối số ngữ cảnh. Using

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
39 you can determine whether this is an early or a late firing, and how many times this window has already fired for this key

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
29

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
30

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
31

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
32

PipelineOptions. The

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 for the current pipeline can always be accessed in a process method by adding it as a parameter

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
33

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
44 methods can also access many of these parameters. Timestamp, Window, key,
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13,
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
24, and
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
47 parameters can all be accessed in an
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
44 method. In addition, an
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
44 method can take a parameter of type
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
50 which tells whether the timer is based on event time or processing time. Timers are explained in more detail in the Timely [and Stateful] Processing with Apache Beam blog post

Timer and State. In addition to aforementioned parameters, user defined Timer and State parameters can be used in a stateful DoFn. Timers and States are explained in more detail in the Timely [and Stateful] Processing with Apache Beam blog post

Timer and State. User defined State parameters can be used in a stateful DoFn. Timers aren’t implemented in the Go SDK yet; see more at Issue 22737. Once implemented, user defined Timer parameters can be used in a stateful DoFn. Timers and States are explained in more detail in the Timely [and Stateful] Processing with Apache Beam blog post

Timer and State. This feature isn’t yet implemented in the Typescript SDK, but we welcome contributions. In the meantime, Typescript pipelines wishing to use state and timers can do so using

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
34

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
35

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
36

4. 6. Composite transforms

Transforms can have a nested structure, where a complex transform performs multiple simpler transforms [such as more than one

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14, or even other composite transforms]. These transforms are called composite transforms. Nesting multiple transforms inside a single composite transform can make your code more modular and easier to understand

The Beam SDK comes packed with many useful composite transforms. See the API reference pages for a list of transforms

  • Pre-written Beam transforms for Java
  • Pre-written Beam transforms for Python
  • Pre-written Beam transforms for Go

4. 6. 1. An example composite transform

The

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 transform in the WordCount example program is an example of a composite transform.
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 is a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 subclass that consists of multiple nested transforms.

In its

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
57 method, the The
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 transform applies the following transform operations.

  1. It applies a
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 on the input
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of text lines, producing an output
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of individual words
  2. It applies the Beam SDK library transform
    public interface MyOptions extends PipelineOptions {
        String getInput[];
        void setInput[String input];
    
        String getOutput[];
        void setOutput[String output];
    }
    62 on the
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of words, producing a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of key/value pairs. Each key represents a word in the text, and each value represents the number of times that word appeared in the original data

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
37

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
38

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
39

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
40

Note. Because

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
62 is itself a composite transform,
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 is also a nested composite transform

4. 6. 2. Creating a composite transform

A PTransform in the Typescript SDK is simply a function that accepts and returns

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
48s such as
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s

Để tạo biến đổi tổng hợp của riêng bạn, hãy tạo một lớp con của lớp

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 và ghi đè phương thức
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
57 để chỉ định logic xử lý thực tế. You can then use this transform just as you would a built-in transform from the Beam SDK

For the

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 class type parameters, you pass the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 types that your transform takes as input, and produces as output. To take multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as input, or produce multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as output, use one of the multi-collection types for the relevant type parameter

To create your own composite

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 call the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
84 method on the current pipeline scope variable. Transforms passed this new sub-
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
84 will be a part of the same composite
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78

To be able to re-use your Composite, build it inside a normal Go function or method. This function is passed a scope and input PCollections, and returns any output PCollections it produces. Note. Such functions cannot be passed directly to

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 functions

The following code sample shows how to declare a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 that accepts a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50s for input, and outputs a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
00s

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
41

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
42

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
39

Within your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 subclass, you’ll need to override the
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
57 method. The
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
57 method is where you add the processing logic for the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78. Your override of
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
57 must accept the appropriate type of input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as a parameter, and specify the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as the return value

The following code sample shows how to override

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
57 for the
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
93 class declared in the previous example

The following code sample shows how to call the

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 composite PTransform, adding it to your pipeline

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
44

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
42

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
46

As long as you override the

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
57 method in your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 subclass to accept the appropriate input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73[s] and return the corresponding output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73[s], you can include as many transforms as you want. These transforms can include core transforms, composite transforms, or the transforms included in the Beam SDK libraries

Your composite

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78s can include as many transforms as you want. These transforms can include core transforms, other composite transforms, or the transforms included in the Beam SDK libraries. They can also consume and return as many
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as are necessary

Your composite transform’s parameters and return value must match the initial input type and final return type for the entire transform, even if the transform’s intermediate data changes type multiple times

Note. The

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
57 method of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 is not meant to be invoked directly by the user of a transform. Instead, you should call the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31 method on the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 itself, with the transform as an argument. This allows transforms to be nested within the structure of your pipeline

4. 6. 3. PTransform Style Guide

The PTransform Style Guide contains additional information not included here, such as style guidelines, logging and testing guidance, and language-specific considerations. The guide is a useful starting point when you want to write new composite PTransforms

5. Pipeline I/O

When you create a pipeline, you often need to read data from some external source, such as a file or a database. Likewise, you may want your pipeline to output its result data to an external storage system. Beam provides read and write transforms for a number of common data storage types. If you want your pipeline to read from or write to a data storage format that isn’t supported by the built-in transforms, you can implement your own read and write transforms

5. 1. Reading input data

Read transforms read data from an external source and return a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 representation of the data for use by your pipeline. You can use a read transform at any point while constructing your pipeline to create a new
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, though it will be most common at the start of your pipeline

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
47

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
48

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
49

5. 2. Ghi dữ liệu đầu ra

Write transforms write the data in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to an external data source. Bạn thường sẽ sử dụng các biến đổi ghi ở cuối quy trình để xuất kết quả cuối cùng của quy trình. Tuy nhiên, bạn có thể sử dụng biến đổi ghi để xuất dữ liệu của
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 tại bất kỳ điểm nào trong quy trình của bạn

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
50

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
51

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
52

5. 3. File-based input and output data

5. 3. 1. Reading from multiple locations

Many read transforms support reading from multiple input files matching a glob operator you provide. Note that glob operators are filesystem-specific and obey filesystem-specific consistency models. The following TextIO example uses a glob operator [

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
009] to read all matching input files that have prefix “input-” and the suffix “. csv” ở vị trí nhất định

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
53

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
54

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
55

To read data from disparate sources into a single

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, read each one independently and then use the transform to create a single
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

5. 3. 2. Writing to multiple output files

For file-based output data, write transforms write to multiple output files by default. When you pass an output file name to a write transform, the file name is used as the prefix for all output files that the write transform produces. You can append a suffix to each output file by specifying a suffix

The following write transform example writes multiple output files to a location. Each file has the prefix “numbers”, a numeric tag, and the suffix “. csv”

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
56

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
57

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
58

5. 4. Beam-provided I/O transforms

See the Beam-provided I/O Transforms page for a list of the currently available I/O transforms

6. Schemas

Often, the types of the records being processed have an obvious structure. Common Beam sources produce JSON, Avro, Protocol Buffer, or database row objects; all of these types have well defined structures, structures that can often be determined by examining the type. Even within a SDK pipeline, Simple Java POJOs [or equivalent structures in other languages] are often used as intermediate types, and these also have a clear structure that can be inferred by inspecting the class. By understanding the structure of a pipeline’s records, we can provide much more concise APIs for data processing

6. 1. What is a schema?

Most structured records share some common characteristics

  • They can be subdivided into separate named fields. Fields usually have string names, but sometimes - as in the case of indexed tuples - have numerical indices instead
  • There is a confined list of primitive types that a field can have. These often match primitive types in most programming languages. int, long, string, etc
  • Often a field type can be marked as optional [sometimes referred to as nullable] or required

Often records have a nested structure. A nested structure occurs when a field itself has subfields so the type of the field itself has a schema. Fields that are array or map types is also a common feature of these structured records

For example, consider the following schema, representing actions in a fictitious e-commerce company

Purchase

Field NameField TypeuserIdSTRINGitemIdINT64shippingAddressROW[ShippingAddress]costINT64transactionsARRAY[ROW[Transaction]]

ShippingAddress

Field NameField TypestreetAddressSTRINGcitySTRINGstatenullable STRINGcountrySTRINGpostCodeSTRING

Transaction

Field NameField TypebankSTRINGpurchaseAmountDOUBLE

Purchase event records are represented by the above purchase schema. Each purchase event contains a shipping address, which is a nested row containing its own schema. Each purchase also contains an array of credit-card transactions [a list, because a purchase might be split across multiple credit cards]; each item in the transaction list is a row with its own schema

This provides an abstract description of the types involved, one that is abstracted away from any specific programming language

Schemas provide us a type-system for Beam records that is independent of any specific programming-language type. There might be multiple Java classes that all have the same schema [for example a Protocol-Buffer class or a POJO class], and Beam will allow us to seamlessly convert between these types. Schemas also provide a simple way to reason about types across different programming-language APIs

A

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with a schema does not need to have a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 specified, as Beam knows how to encode and decode Schema rows; Beam uses a special coder to encode schema types

6. 2. Schemas for programming language types

While schemas themselves are language independent, they are designed to embed naturally into the programming languages of the Beam SDK being used. This allows Beam users to continue using native types while reaping the advantage of having Beam understand their element schemas

In Java you could use the following set of classes to represent the purchase schema. Beam will automatically infer the correct schema based on the members of the class

In Python you can use the following set of classes to represent the purchase schema. Beam will automatically infer the correct schema based on the members of the class

Trong Go, mã hóa lược đồ được sử dụng theo mặc định cho các loại cấu trúc, với các trường Đã xuất trở thành một phần của lược đồ. Beam will automatically infer the schema based on the fields and field tags of the struct, and their order

In Typescript, JSON objects are used to represent schema’d data. Unfortunately type information in Typescript is not propagated to the runtime layer, so it needs to be manually specified in some places [e. g. when using cross-language pipelines]

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
59

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
60

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
61

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
62

Using JavaBean classes as above is one way to map a schema to Java classes. However multiple Java classes might have the same schema, in which case the different Java types can often be used interchangeably. Beam will add implicit conversions between types that have matching schemas. For example, the above

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
014 class has the same schema as the following class

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
63

So if we had two

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as follows

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
64

Then these two

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s would have the same schema, even though their Java types would be different. This means for example the following two code snippets are valid

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
65

and

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
66

Even though the in both cases the

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
23 parameter differs from the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73's Java type, since the schemas are the same Beam will automatically make the conversion. The built-in
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
019 transform can also be used to translate between Java types of equivalent schemas, as detailed below

6. 3. Schema definition

The schema for a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 defines elements of that
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as an ordered list of named fields. Each field has a name, a type, and possibly a set of user options. The type of a field can be primitive or composite. The following are the primitive types currently supported by Beam

TypeDescriptionBYTEAn 8-bit signed valueINT16A 16-bit signed valueINT32A 32-bit signed valueINT64A 64-bit signed valueDECIMALAn arbitrary-precision decimal typeFLOATA 32-bit IEEE 754 floating point numberDOUBLEA 64-bit IEEE 754 floating point numberSTRINGA stringDATETIMEA timestamp represented as milliseconds since the epochBOOLEANA boolean valueBYTESA raw byte array

A field can also reference a nested schema. In this case, the field will have type ROW, and the nested schema will be an attribute of this field type

Three collection types are supported as field types. ARRAY, ITERABLE and MAP

  • ARRAY This represents a repeated value type, where the repeated elements can have any supported type. Arrays of nested rows are supported, as are arrays of arrays
  • ITERABLE This is very similar to the array type, it represents a repeated value, but one in which the full list of items is not known until iterated over. This is intended for the case where an iterable might be larger than the available memory, and backed by external storage [for example, this can happen with the iterable returned by a
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    14]. The repeated elements can have any supported type
  • MAP This represents an associative map from keys to values. All schema types are supported for both keys and values. Values that contain map types cannot be used as keys in any grouping operation

6. 4. Logical types

Users can extend the schema type system to add custom logical types that can be used as a field. A logical type is identified by a unique identifier and an argument. A logical type also specifies an underlying schema type to be used for storage, along with conversions to and from that type. As an example, a logical union can always be represented as a row with nullable fields, where the user ensures that only one of those fields is ever set at a time. Tuy nhiên, điều này có thể tẻ nhạt và phức tạp để quản lý. The OneOf logical type provides a value class that makes it easier to manage the type as a union, while still using a row with nullable fields as its underlying storage. Mỗi loại logic cũng có một mã định danh duy nhất, vì vậy chúng cũng có thể được giải thích bằng các ngôn ngữ khác. Thêm ví dụ về các loại logic được liệt kê dưới đây

6. 4. 1. Định nghĩa kiểu logic

Để xác định loại logic, bạn phải chỉ định loại Lược đồ được sử dụng để biểu thị loại cơ bản cũng như mã định danh duy nhất cho loại đó. Một loại logic áp đặt ngữ nghĩa bổ sung lên trên một loại lược đồ. Ví dụ: một loại logic để biểu thị dấu thời gian nano giây được biểu diễn dưới dạng lược đồ chứa trường INT64 và INT32. Chỉ riêng lược đồ này không nói bất cứ điều gì về cách diễn giải loại này, tuy nhiên, loại logic cho bạn biết rằng lược đồ này biểu thị dấu thời gian nano giây, với trường INT64 biểu thị giây và trường INT32 biểu thị nano giây

Các kiểu logic cũng được chỉ định bởi một đối số, cho phép tạo một lớp gồm các kiểu liên quan. Ví dụ: loại thập phân có độ chính xác giới hạn sẽ có đối số số nguyên cho biết có bao nhiêu chữ số chính xác được biểu thị. Đối số được biểu thị bằng một loại lược đồ, vì vậy bản thân nó có thể là một loại phức tạp

Trong Java, một kiểu logic được chỉ định là một lớp con của lớp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
023. Một lớp Java tùy chỉnh có thể được chỉ định để biểu diễn kiểu logic và các hàm chuyển đổi phải được cung cấp để chuyển đổi qua lại giữa lớp Java này và biểu diễn kiểu Lược đồ bên dưới. Ví dụ: loại logic biểu thị dấu thời gian nano giây có thể được triển khai như sau

Trong Go, một loại logic được chỉ định với triển khai tùy chỉnh của giao diện

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
024. Ví dụ: nhà cung cấp loại logic đại diện cho dấu thời gian nano giây có thể được triển khai như sau

Trong Bản mô tả, một loại logic được xác định bởi giao diện LogicalTypeInfo liên kết URN của một loại logic với biểu diễn của nó và chuyển đổi của nó sang và từ biểu diễn này

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
67

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
68

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
69

6. 4. 2. Useful logical types

Currently the Python SDK provides minimal convenience logical types, other than to handle

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
025

Currently the Go SDK provides minimal convenience logical types, other than to handle additional integer primitives, and

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
026

EnumerationType

This convenience builder doesn’t yet exist for the Python SDK

This convenience builder doesn’t yet exist for the Go SDK

This logical type allows creating an enumeration type consisting of a set of named constants

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
70

The value of this field is stored in the row as an INT32 type, however the logical type defines a value type that lets you access the enumeration either as a string or a value. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
71

Given a row object with an enumeration field, you can also extract the field as the enumeration value

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
72

Automatic schema inference from Java POJOs and JavaBeans automatically converts Java enums to EnumerationType logical types

OneOfType

This convenience builder doesn’t yet exist for the Python SDK

This convenience builder doesn’t yet exist for the Go SDK

OneOfType allows creating a disjoint union type over a set of schema fields. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
73

The value of this field is stored in the row as another Row type, where all the fields are marked as nullable. The logical type however defines a Value object that contains an enumeration value indicating which field was set and allows getting just that field

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
74

In the above example we used the field names in the switch statement for clarity, however the enum integer values could also be used

6. 5. Creating Schemas

In order to take advantage of schemas, your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s must have a schema attached to it. Often, the source itself will attach a schema to the PCollection. For example, when using
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
028 to read Avro files, the source can automatically infer a Beam schema from the Avro schema and attach that to the Beam
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. However not all sources produce schemas. In addition, often Beam pipelines have intermediate stages and types, and those also can benefit from the expressiveness of schemas

6. 5. 1. Inferring schemas

Thích ứng cho
  • SDK Java
  • SDK Python
  • Truy cập SDK
  • SDK TypeScript

Unfortunately, Beam is unable to access Typescript’s type information at runtime. Schemas must be manually declared with

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
030. On the other hand, schema-aware operations such as
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
90 can be used without an explicit schema declared

Beam is able to infer schemas from a variety of common Java types. The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
032 annotation can be used to tell Beam to infer schemas from a specific type. The annotation takes a
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
033 as an argument, and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
033 classes are already built in for common Java types. The
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
035 can also be invoked programmatically for cases where it is not practical to annotate the Java type itself

Java POJOs

A POJO [Plain Old Java Object] is a Java object that is not bound by any restriction other than the Java Language Specification. Một POJO có thể chứa các biến thành viên là nguyên hàm, là các POJO khác hoặc là các bản đồ bộ sưu tập hoặc mảng của chúng. POJOs do not have to extend prespecified classes or extend any specific interfaces

If a POJO class is annotated with

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
036, Beam will automatically infer a schema for this class. Nested classes are supported as are classes with
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
83, array, and
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
70 fields

For example, annotating the following class tells Beam to infer a schema from this POJO class and apply it to any

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
039

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
75

The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
040 annotation tells Beam that this constructor can be used to create instances of TransactionPojo, assuming that constructor parameters have the same names as the field names.
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
040 can also be used to annotate static factory methods on the class, allowing the constructor to remain private. If there is no
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
040 annotation then all the fields must be non-final and the class must have a zero-argument constructor

There are a couple of other useful annotations that affect how Beam infers schemas. By default the schema field names inferred will match that of the class field names. However

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
043 can be used to specify a different name to be used for the schema field.
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
044 can be used to mark specific class fields as excluded from the inferred schema. For example, it’s common to have ephemeral fields in a class that should not be included in a schema [e. g. caching the hash value to prevent expensive recomputation of the hash], and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
044 can be used to exclude these fields. Note that ignored fields will not be included in the encoding of these records

In some cases it is not convenient to annotate the POJO class, for example if the POJO is in a different package that is not owned by the Beam pipeline author. In these cases the schema inference can be triggered programmatically in pipeline’s main function as follows

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
76

Java Beans

Java Beans are a de-facto standard for creating reusable property classes in Java. While the full standard has many characteristics, the key ones are that all properties are accessed via getter and setter classes, and the name format for these getters and setters is standardized. A Java Bean class can be annotated with

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
046 and Beam will automatically infer a schema for this class. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
77

The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
040 annotation can be used to specify a constructor or a static factory method, in which case the setters and zero-argument constructor can be omitted

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
78

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
043 and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
044 can be used to alter the schema inferred, just like with POJO classes

AutoValue

Java value classes are notoriously difficult to generate correctly. There is a lot of boilerplate you must create in order to properly implement a value class. AutoValue is a popular library for easily generating such classes by implementing a simple abstract base class

Beam can infer a schema from an AutoValue class. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
79

This is all that’s needed to generate a simple AutoValue class, and the above

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
032 annotation tells Beam to infer a schema from it. This also allows AutoValue elements to be used inside of
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
043 and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
044 can be used to alter the schema inferred

Beam has a few different mechanisms for inferring schemas from Python code

các lớp NamedTuple

A class is a Python class that wraps a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
44, assigning a name to each element and restricting it to a particular type. Beam sẽ tự động suy ra lược đồ cho PCollections với các loại đầu ra
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
055. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
80

chùm tia. Hàng và Chọn

Ngoài ra còn có các phương pháp để tạo khai báo lược đồ đặc biệt. First, you can use a lambda that returns instances of

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
056

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
81

Sometimes it can be more concise to express the same logic with the transform

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
82

Note that these declaration don’t include any specific information about the types of the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
058 and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
059 fields, so Beam will attempt to infer type information. If it’s unable to it will fall back to the generic type
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
060. Sometimes this is not ideal, you can use casts to make sure Beam correctly infers types with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
056 or with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
057

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
83

Beam currently only infers schemas for exported fields in Go structs

Structs

Beam will automatically infer schemas for all Go structs used as PCollection elements, and default to encoding them using schema encoding

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
84

Unexported fields are ignored, and cannot be automatically inferred as part of the schema. Fields of type func, channel, unsafe. Pointer, or uintptr will be ignored by inference. Fields of interface types are ignored, unless a schema provider is registered for them

By default, schema field names will match the exported struct field names. In the above example, “Bank” and “PurchaseAmount” are the schema field names. A schema field name can be overridden with a struct tag for the field

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
85

Overriding schema field names is useful for compatibility cross language transforms, as schema fields may have different requirements or restrictions from Go exported fields

6. 6. Using Schema Transforms

A schema on a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 enables a rich variety of relational transforms. The fact that each record is composed of named fields allows for simple and readable aggregations that reference fields by name, similar to the aggregations in a SQL expression

Beam does not yet support Schema transforms natively in Go. However, it will be implemented with the following behavior

6. 6. 1. Field selection syntax

The advantage of schemas is that they allow referencing of element fields by name. Beam provides a selection syntax for referencing fields, including nested and repeated fields. This syntax is used by all of the schema transforms when referencing the fields they operate on. The syntax can also be used inside of a DoFn to specify which schema fields to process

Addressing fields by name still retains type safety as Beam will check that schemas match at the time the pipeline graph is constructed. If a field is specified that does not exist in the schema, the pipeline will fail to launch. In addition, if a field is specified with a type that does not match the type of that field in the schema, the pipeline will fail to launch

The following characters are not allowed in field names. . * [ ] { }

Top-level fields

In order to select a field at the top level of a schema, the name of the field is specified. For example, to select just the user ids from a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of purchases one would write [using the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
057 transform]

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
86

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
87

Nested fields

Support for Nested fields hasn’t been developed for the Python SDK yet

Support for Nested fields hasn’t been developed for the Go SDK yet

Individual nested fields can be specified using the dot operator. For example, to select just the postal code from the shipping address one would write

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
88

Wildcards

Support for wildcards hasn’t been developed for the Python SDK yet

Support for wildcards hasn’t been developed for the Go SDK yet

The * operator can be specified at any nesting level to represent all fields at that level. For example, to select all shipping-address fields one would write

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
89

Arrays

An array field, where the array element type is a row, can also have subfields of the element type addressed. Khi được chọn, kết quả là một mảng của loại trường con đã chọn. For example

Support for Array fields hasn’t been developed for the Python SDK yet

Support for Array fields hasn’t been developed for the Go SDK yet

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
90

Will result in a row containing an array field with element-type string, containing the list of banks for each transaction

While the use of [] brackets in the selector is recommended, to make it clear that array elements are being selected, they can be omitted for brevity. In the future, array slicing will be supported, allowing selection of portions of the array

Maps

A map field, where the value type is a row, can also have subfields of the value type addressed. When selected, the result is a map where the keys are the same as in the original map but the value is the specified type. Similar to arrays, the use of {} curly brackets in the selector is recommended, to make it clear that map value elements are being selected, they can be omitted for brevity. In the future, map key selectors will be supported, allowing selection of specific keys from the map. For example, given the following schema

PurchasesByType

Field NameField TypepurchasesMAP{STRING, ROW{PURCHASE}

The following

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
91

Support for Map fields hasn’t been developed for the Python SDK yet

Support for Map fields hasn’t been developed for the Go SDK yet

Sẽ dẫn đến một hàng chứa trường bản đồ với chuỗi loại khóa và chuỗi loại giá trị. Bản đồ đã chọn sẽ chứa tất cả các khóa từ bản đồ gốc và các giá trị sẽ là userId có trong bản ghi mua hàng

Mặc dù nên sử dụng dấu ngoặc {} trong bộ chọn, nhưng để làm rõ rằng các phần tử giá trị bản đồ đang được chọn, chúng có thể được bỏ qua cho ngắn gọn. Trong tương lai, tính năng cắt bản đồ sẽ được hỗ trợ, cho phép chọn các phím cụ thể từ bản đồ

6. 6. 2. Biến đổi lược đồ

Beam cung cấp một tập hợp các biến đổi hoạt động tự nhiên trên các lược đồ. Các biến đổi này rất biểu cảm, cho phép lựa chọn và tổng hợp theo các trường lược đồ được đặt tên. Sau đây là một số ví dụ về biến đổi lược đồ hữu ích

Chọn đầu vào

Often a computation is only interested in a subset of the fields in an input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
057 transform allows one to easily project out only the fields of interest. The resulting
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 has a schema containing each selected field as a top-level field. Có thể chọn cả trường cấp cao nhất và trường lồng nhau. Ví dụ: trong lược đồ Mua hàng, người ta chỉ có thể chọn các trường userId và streetAddress như sau

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
92

Support for Nested fields hasn’t been developed for the Python SDK yet

Support for Nested fields hasn’t been developed for the Go SDK yet

The resulting

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 will have the following schema

Field NameField TypeuserIdSTRINGstreetAddressSTRING

Điều này cũng đúng với các lựa chọn ký tự đại diện. Sau đây

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
93

Hỗ trợ cho Ký tự đại diện chưa được phát triển cho Python SDK

Support for Wildcards hasn’t been developed for the Go SDK yet

Will result in the following schema

Field NameField TypeuserIdSTRINGstreetAddressSTRINGcitySTRINGstatenullable STRINGcountrySTRINGpostCodeSTRING

When selecting fields nested inside of an array, the same rule applies that each selected field appears separately as a top-level field in the resulting row. This means that if multiple fields are selected from the same nested row, each selected field will appear as its own array field. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
94

Support for nested fields hasn’t been developed for the Python SDK yet

Support for nested fields hasn’t been developed for the Go SDK yet

Will result in the following schema

Field NameField TypebankARRAY[STRING]purchaseAmountARRAY[DOUBLE]

Wildcard selections are equivalent to separately selecting each field

Selecting fields nested inside of maps have the same semantics as arrays. If you select multiple fields from a map , then each selected field will be expanded to its own map at the top level. This means that the set of map keys will be copied, once for each selected field

Sometimes different nested rows will have fields with the same name. Selecting multiple of these fields would result in a name conflict, as all selected fields are put in the same row schema. When this situation arises, the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
070 builder method can be used to provide an alternate name for the selected field

Another use of the Select transform is to flatten a nested schema into a single flat schema. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
95

Support for nested fields hasn’t been developed for the Python SDK yet

Support for nested fields hasn’t been developed for the Go SDK yet

Will result in the following schema

Field NameField TypeuserIdSTRINGitemIdSTRINGshippingAddress_streetAddressSTRINGshippingAddress_citynullable STRINGshippingAddress_stateSTRINGshippingAddress_countrySTRINGshippingAddress_postCodeSTRINGcostCentsINT64transactions_bankARRAY[STRING]transactions_purchaseAmountARRAY[DOUBLE]

Grouping aggregations

The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
071 transform allows simply grouping data by any number of fields in the input schema, applying aggregations to those groupings, and storing the result of those aggregations in a new schema field. The output of the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
071 transform has a schema with one field corresponding to each aggregation performed

The

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
90 transform allows simply grouping data by any number of fields in the input schema, applying aggregations to those groupings, and storing the result of those aggregations in a new schema field. The output of the
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
90 transform has a schema with one field corresponding to each aggregation performed

The simplest usage of

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
071 specifies no aggregations, in which case all inputs matching the provided set of fields are grouped together into an
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
076 field. For example

The simplest usage of

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
90 specifies no aggregations, in which case all inputs matching the provided set of fields are grouped together into an
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
076 field. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
96

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
97

Support for schema-aware grouping hasn’t been developed for the Go SDK yet

The output schema of this is

Field NameField TypekeyROW{userId. STRING, bank. STRING}valuesITERABLE[ROW[Purchase]]

The key field contains the grouping key and the values field contains a list of all the values that matched that key

The names of the key and values fields in the output schema can be controlled using this withKeyField and withValueField builders, as follows

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
98

It is quite common to apply one or more aggregations to the grouped result. Each aggregation can specify one or more fields to aggregate, an aggregation function, and the name of the resulting field in the output schema. For example, the following application computes three aggregations grouped by userId, with all aggregations represented in a single output schema

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
99

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
00

Support for schema-aware grouping hasn’t been developed for the Go SDK yet

The result of this aggregation will have the following schema

Field NameField TypekeyROW{userId. STRING}valueROW{numPurchases. INT64, totalSpendCents. INT64, topPurchases. ARRAY[INT64]}

Often

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
079 will be use to flatten the result into a non-nested, flat schema

Joins

Beam supports equijoins on schema

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
40 - namely joins where the join condition depends on the equality of a subset of fields. For example, the following examples uses the Purchases schema to join transactions with the reviews that are likely associated with that transaction [both the user and product match that in the transaction]. This is a “natural join” - one in which the same field names are used on both the left-hand and right-hand sides of the join - and is specified with the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
081 keyword

Support for joins hasn’t been developed for the Python SDK yet

Support for joins hasn’t been developed for the Go SDK yet

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
01

The resulting schema is the following

Field NameField TypelhsROW{Transaction}rhsROW{Review}

Each resulting row contains one Transaction and one Review that matched the join condition

If the fields to match in the two schemas have different names, then the on function can be used. For example, if the Review schema named those fields differently than the Transaction schema, then we could write the following

Support for joins hasn’t been developed for the Python SDK yet

Support for joins hasn’t been developed for the Go SDK yet

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
02

In addition to inner joins, the Join transform supports full outer joins, left outer joins, and right outer joins

Complex joins

While most joins tend to be binary joins - joining two inputs together - sometimes you have more than two input streams that all need to be joined on a common key. The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
082 transform allows joining multiple
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
40 together based on equality of schema fields. Each
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 can be marked as required or optional in the final join record, providing a generalization of outer joins to joins with greater than two input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. The output can optionally be expanded - providing individual joined records, as in the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
086 transform. The output can also be processed in unexpanded format - providing the join key along with Iterables of all records from each input that matched that key

Support for joins hasn’t been developed for the Python SDK yet

Support for joins hasn’t been developed for the Go SDK yet

Filtering events

The

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
74 transform can be configured with a set of predicates, each one based one specified fields. Only records for which all predicates return true will pass the filter. For example the following

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
03

Will produce all purchases made from Germany with a purchase price of greater than twenty cents

Adding fields to a schema

The AddFields transform can be used to extend a schema with new fields. Input rows will be extended to the new schema by inserting null values for the new fields, though alternate default values can be specified; if the default null value is used then the new field type will be marked as nullable. Nested subfields can be added using the field selection syntax, including nested fields inside arrays or map values

For example, the following application

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
04

Results in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with an expanded schema. All of the rows and fields of the input, but also with the specified fields added to the schema. All resulting rows will have null values filled in for the timeOfDaySeconds and the shippingAddress. deliveryNotes fields, and a false value filled in for the transactions. isFlagged field

Removing fields from a schema

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
089 allows specific fields to be dropped from a schema. Input rows will have their schemas truncated, and any values for dropped fields will be removed from the output. Nested fields can also be dropped using the field selection syntax

For example, the following snippet

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
05

Results in a copy of the input with those two fields and their corresponding values removed

Renaming schema fields

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
090 allows specific fields in a schema to be renamed. The field values in input rows are left unchanged, only the schema is modified. This transform is often used to prepare records for output to a schema-aware sink, such as an RDBMS, to make sure that the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 schema field names match that of the output. It can also be used to rename fields generated by other transforms to make them more usable [similar to SELECT AS in SQL]. Nested fields can also be renamed using the field-selection syntax

For example, the following snippet

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
06

Results in the same set of unmodified input elements, however the schema on the PCollection has been changed to rename userId to userIdentifier and shippingAddress. đường phốĐịa chỉ giao hàngĐịa chỉ. street

Converting between types

As mentioned, Beam can automatically convert between different Java types, as long as those types have equivalent schemas. One way to do this is by using the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
019 transform, as follows

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
07

Beam will validate that the inferred schema for

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
093 matches that of the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, and will then cast to a
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
095

Since the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
096 class can support any schema, any
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with schema can be cast to a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of rows, as follows

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
08

Nếu loại nguồn là lược đồ một trường, Convert cũng sẽ chuyển đổi thành loại trường nếu được hỏi, mở hộp hiệu quả. Ví dụ: đưa ra một lược đồ với một trường INT64 duy nhất, phần sau đây sẽ chuyển đổi nó thành một

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
099

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
09

In all cases, type checking is done at pipeline graph construction, and if the types do not match the schema then the pipeline will fail to launch

6. 6. 3. Schemas in ParDo

A

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with a schema can apply a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, just like any other
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. However the Beam runner is aware of schemas when applying a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, which enables additional functionality

Input conversion

Beam does not yet support input conversion in Go

Since Beam knows the schema of the source

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, it can automatically convert the elements to any Java type for which a matching schema is known. For example, using the above-mentioned Transaction schema, say we have the following
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
10

If there were no schema, then the applied

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 would have to accept an element of type
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
107. However since there is a schema, you could apply the following DoFn

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
11

Even though the

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
23 parameter does not match the Java type of the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, since it has a matching schema Beam will automatically convert elements. If the schema does not match, Beam will detect this at graph-construction time and will fail the job with a type error

Since every schema can be represented by a Row type, Row can also be used here

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
12

Input selection

Vì đầu vào có lược đồ nên bạn cũng có thể tự động chọn các trường cụ thể để xử lý trong DoFn

Với các giao dịch mua ở trên

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, giả sử bạn chỉ muốn xử lý các trường userId và itemId. You can do these using the above-described selection expressions, as follows

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
13

You can also select nested fields, as follows

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
14

For more information, see the section on field-selection expressions. When selecting subschemas, Beam will automatically convert to any matching schema type, just like when reading the entire row

7. Data encoding and type safety

Thích ứng cho
  • SDK Java
  • SDK Python
  • Truy cập SDK
  • SDK TypeScript

When Beam runners execute your pipeline, they often need to materialize the intermediate data in your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, which requires converting elements to and from byte strings. The Beam SDKs use objects called
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66s to describe how the elements of a given
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 may be encoded and decoded

Note that coders are unrelated to parsing or formatting data when interacting with external data sources or sinks. Such parsing or formatting should typically be done explicitly, using transforms such as

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 or
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
69

In the Beam SDK for Java, the type

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 provides the methods required for encoding and decoding data. The SDK for Java provides a number of Coder subclasses that work with a variety of standard Java types, such as Integer, Long, Double, StringUtf8 and more. You can find all of the available Coder subclasses in the Coder package

In the Beam SDK for Python, the type

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 provides the methods required for encoding and decoding data. The SDK for Python provides a number of Coder subclasses that work with a variety of standard Python types, such as primitive types, Tuple, Iterable, StringUtf8 and more. You can find all of the available Coder subclasses in the apache_beam. coders package

Standard Go types like

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
119
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
120,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
121, and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96 and more are coded using builtin coders. Structs and pointers to structs default using Beam Schema Row encoding. However, users can build and register custom coders with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
123. You can find available Coder functions in the coder package

Standard Typescript types like

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
124,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
125 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96 and more are coded using builtin coders. Json objects and arrays are encoded via a BSON encoding. For these types, coders need not be specified unless interacting with cross-language transforms. Users can build custom coders by extending
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
127 for use with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
128, but generally logical types are preferred for this case

Note that coders do not necessarily have a 1. 1 relationship with types. For example, the Integer type can have multiple valid coders, and input and output data can use different Integer coders. A transform might have Integer-typed input data that uses BigEndianIntegerCoder, and Integer-typed output data that uses VarIntCoder

7. 1. Specifying coders

The Beam SDKs require a coder for every

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 in your pipeline. In most cases, the Beam SDK is able to automatically infer a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 based on its element type or the transform that produces it, however, in some cases the pipeline author will need to specify a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 explicitly, or develop a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for their custom type

You can explicitly set the coder for an existing

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by using the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
135. Note that you cannot call
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
136 on a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that has been finalized [e. g. by calling
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
138 on it]

You can get the coder for an existing

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by using the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
140. This method will fail with an
--=
29 if a coder has not been set and cannot be inferred for the given
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

Beam SDKs use a variety of mechanisms when attempting to automatically infer the

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

Each pipeline object has a

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145. The
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145 represents a mapping of Java types to the default coders that the pipeline should use for
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s of each type

The Beam SDK for Python has a

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145 that represents a mapping of Python types to the default coder that should be used for
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s of each type

The Beam SDK for Go allows users to register default coder implementations with

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
123

By default, the Beam SDK for Java automatically infers the

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the elements of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 produced by a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 using the type parameter from the transform’s function object, such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. In the case of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, for example, a
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
156 function object accepts an input element of type
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
00 and produces an output element of type
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50. In such a case, the SDK for Java will automatically infer the default
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the output
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
160 [in the default pipeline
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145, this is
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
162]

By default, the Beam SDK for Python automatically infers the

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the elements of an output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 using the typehints from the transform’s function object, such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. In the case of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, for example a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 with the typehints
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
168 and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
169 accepts an input element of type int and produces an output element of type str. In such a case, the Beam SDK for Python will automatically infer the default
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [in the default pipeline
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145, this is
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
173]

By default, the Beam SDK for Go automatically infers the

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the elements of an output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by the output of the transform’s function object, such as a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. In the case of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, for example a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 with the parameters of
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
179 accepts an input element of type
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01 and produces an output element of type
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96. In such a case, the Beam SDK for Go will automatically infer the default
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to be the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
184 coder

Note. If you create your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 from in-memory data by using the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 transform, you cannot rely on coder inference and default coders.
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 does not have access to any typing information for its arguments, and may not be able to infer a coder if the argument list contains a value whose exact run-time class doesn’t have a default coder registered

Khi sử dụng

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94, cách đơn giản nhất để đảm bảo rằng bạn có bộ mã hóa chính xác là gọi ________ 45 ______ 189 khi bạn áp dụng phép biến đổi
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94

7. 2. Default coders and the CoderRegistry

Each Pipeline object has a

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145 object, which maps language types to the default coder the pipeline should use for those types. You can use the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145 yourself to look up the default coder for a given type, or to register a new default coder for a given type

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145 contains a default mapping of coders to standard JavaPython types for any pipeline you create using the Beam SDK for JavaPython . The following table shows the standard mapping.

Java TypeDefault CoderDoubleDoubleCoderInstantInstantCoderIntegerVarIntCoderIterableIterableCoderKVKvCoderListListCoderMapMapCoderLongVarLongCoderStringStringUtf8CoderTableRowTableRowJsonCoderVoidVoidCoderbyte[ ]ByteArrayCoderTimestampedValueTimestampedValueCoder

Python TypeDefault CoderintVarIntCoderfloatFloatCoderstrBytesCoderbytesStrUtf8CoderTupleTupleCoder

7. 2. 1. Looking up a default coder

You can use the method

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
194 to determine the default Coder for a Java type. You can access the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145 for a given pipeline by using the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
196. This allows you to determine [or set] the default Coder for a Java type on a per-pipeline basis. i. e. “for this pipeline, verify that Integer values are encoded using
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
197. ”

You can use the method

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
198 to determine the default Coder for a Python type. You can use
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
199 to access the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145. This allows you to determine [or set] the default Coder for a Python type

You can use the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
201 function to determine the default Coder for a Go type

7. 2. 2. Setting the default coder for a type

To set the default Coder for a JavaPython type for a particular pipeline, you obtain and modify the pipeline’s

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145. You use the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
196
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
199
to get the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
145 object, and then use the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
206
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
207
to register a new
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the target type.

To set the default Coder for a Go type you use the function

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
123 to register a encoder and decoder functions for the target type. However, built in types like
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
120, etc cannot have their coders override

Mã ví dụ sau minh họa cách đặt Coder mặc định, trong trường hợp này là

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
197, cho Số nguyênint values for a pipeline.

The following example code demonstrates how to set a custom Coder for

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
214 elements

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
15

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
16

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
17

7. 2. 3. Annotating a custom data type with a default coder

If your pipeline program defines a custom data type, you can use the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
215 annotation to specify the coder to use with that type. By default, Beam will use
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
216 which uses Java serialization, but it has drawbacks

  1. It is inefficient in encoding size and speed. See this comparison of Java serialization methods

  2. It is non-deterministic. it may produce different binary encodings for two equivalent objects

    For key/value pairs, the correctness of key-based operations [GroupByKey, Combine] and per-key State depends on having a deterministic coder for the key

Bạn có thể sử dụng chú thích

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
215 để đặt mặc định mới như sau

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
18

If you’ve created a custom coder to match your data type, and you want to use the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
215 annotation, your coder class must implement a static
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
219 factory method

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
19

The Beam SDK for PythonGo does not support annotating data types with a default coder. If you would like to set a default coder, use the method described in the previous section, Setting the default coder for a type.

8. Windowing

Windowing subdivides a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 according to the timestamps of its individual elements. Transforms that aggregate multiple elements, such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15, work implicitly on a per-window basis — they process each
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as a succession of multiple, finite windows, though the entire collection itself may be of unbounded size

A related concept, called triggers, determines when to emit the results of aggregation as unbounded data arrives. You can use triggers to refine the windowing strategy for your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Triggers allow you to deal with late-arriving data or to provide early results. See the section for more information

8. 1. Windowing basics

Some Beam transforms, such as

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15, group multiple elements by a common key. Ordinarily, that grouping operation groups all of the elements that have the same key within the entire data set. With an unbounded data set, it is impossible to collect all of the elements, since new elements are constantly being added and may be infinitely many [e. g. streaming data]. Nếu bạn đang làm việc với các
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn, cửa sổ đặc biệt hữu ích

In the Beam model, any

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [including unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s] can be subdivided into logical windows. Each element in a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 is assigned to one or more windows according to the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73's windowing function, and each individual window contains a finite number of elements. Grouping transforms then consider each
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73's elements on a per-window basis.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14, for example, implicitly groups the elements of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by key and window

Caution. Beam’s default windowing behavior is to assign all elements of a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to a single, global window and discard late data, even for unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. Before you use a grouping transform such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 on an unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, you must do at least one of the following

  • Set a non-global windowing function. See
  • Set a non-default . This allows the global window to emit results under other conditions, since the default windowing behavior [waiting for all data to arrive] will never occur

If you don’t set a non-global windowing function or a non-default trigger for your unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 and subsequently use a grouping transform such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15, your pipeline will generate an error upon construction and your job will fail

8. 1. 1. Windowing constraints

After you set the windowing function for a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, the elements’ windows are used the next time you apply a grouping transform to that
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Window grouping occurs on an as-needed basis. If you set a windowing function using the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
244 transform, each element is assigned to a window, but the windows are not considered until
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 aggregates across a window and key. This can have different effects on your pipeline. Consider the example pipeline in the figure below

Figure 3. Pipeline applying windowing

In the above pipeline, we create an unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by reading a set of key/value pairs using
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
248, and then apply a windowing function to that collection using the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
244 transform. We then apply a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 to the collection, and then later group the result of that
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 using
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14. The windowing function has no effect on the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform, because the windows are not actually used until they’re needed for the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14. Subsequent transforms, however, are applied to the result of the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 – data is grouped by both key and window

8. 1. 2. Windowing with bounded PCollections

You can use windowing with fixed-size data sets in bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. However, note that windowing considers only the implicit timestamps attached to each element of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, and data sources that create fixed data sets [such as
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
258] assign the same timestamp to every element. This means that all the elements are by default part of a single, global window

To use windowing with fixed data sets, you can assign your own timestamps to each element. To assign timestamps to elements, use a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform with a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 that outputs each element with a new timestamp [for example, the WithTimestamps transform in the Beam SDK for Java]

To illustrate how windowing with a bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 can affect how your pipeline processes data, consider the following pipeline

Figure 4.

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 without windowing, on a bounded collection

In the above pipeline, we create a bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by reading lines from a file using
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
258. We then group the collection using
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14, and apply a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform to the grouped
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. In this example, the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 creates a collection of unique keys, and then
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 gets applied exactly once per key

Lưu ý rằng ngay cả khi bạn không đặt chức năng tạo cửa sổ, thì vẫn có một cửa sổ – tất cả các thành phần trong

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn được gán cho một cửa sổ chung duy nhất

Now, consider the same pipeline, but using a windowing function

Figure 5.

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 with windowing, on a bounded collection

As before, the pipeline creates a bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by reading lines from a file. We then set a for that
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 transform groups the elements of the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by both key and window, based on the windowing function. The subsequent
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform gets applied multiple times per key, once for each window

8. 2. Provided windowing functions

You can define different kinds of windows to divide the elements of your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Beam provides several windowing functions, including

  • Fixed Time Windows
  • Sliding Time Windows
  • Per-Session Windows
  • Single Global Window
  • Calendar-based Windows [not supported by the Beam SDK for Python or Go]

You can also define your own

--=
45 if you have a more complex need

Note that each element can logically belong to more than one window, depending on the windowing function you use. Sliding time windowing, for example, can create overlapping windows wherein a single element can be assigned to multiple windows. However, each element in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 can only be in one window, so if an element is assigned to multiple windows, the element is conceptually duplicated into each of the windows and each element is identical except for its window

8. 2. 1. Fixed time windows

The simplest form of windowing is using fixed time windows. given a timestamped

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 which might be continuously updating, each window might capture [for example] all elements with timestamps that fall into a 30 second interval

A fixed time window represents a consistent duration, non overlapping time interval in the data stream. Consider windows with a 30 second duration. all of the elements in your unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with timestamp values from 0. 00. 00 up to [but not including] 0. 00. 30 belong to the first window, elements with timestamp values from 0. 00. 30 up to [but not including] 0. 01. 00 belong to the second window, and so on

Figure 6. Cửa sổ thời gian cố định, thời lượng 30 giây

8. 2. 2. Sliding time windows

A sliding time window also represents time intervals in the data stream; however, sliding time windows can overlap. Ví dụ: mỗi cửa sổ có thể thu thập dữ liệu trị giá 60 giây nhưng cứ sau 30 giây lại có một cửa sổ mới bắt đầu. The frequency with which sliding windows begin is called the period. Do đó, ví dụ của chúng tôi sẽ có thời lượng cửa sổ là 60 giây và khoảng thời gian là 30 giây

Vì nhiều cửa sổ chồng lên nhau nên hầu hết các thành phần trong tập dữ liệu sẽ thuộc về nhiều cửa sổ. Loại cửa sổ này rất hữu ích để lấy dữ liệu trung bình đang chạy;

Hình 7. Sliding time windows, with 1 minute window duration and 30s window period

8. 2. 3. Session windows

A session window function defines windows that contain elements that are within a certain gap duration of another element. Session windowing applies on a per-key basis and is useful for data that is irregularly distributed with respect to time. For example, a data stream representing user mouse activity may have long periods of idle time interspersed with high concentrations of clicks. If data arrives after the minimum specified gap duration time, this initiates the start of a new window

Figure 8. Session windows, with a minimum gap duration. Note how each data key has different windows, according to its data distribution

8. 2. 4. The single global window

By default, all data in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 is assigned to the single global window, and late data is discarded. If your data set is of a fixed size, you can use the global window default for your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

You can use the single global window if you are working with an unbounded data set [e. g. from a streaming data source] but use caution when applying aggregating transforms such as

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15. Cửa sổ chung duy nhất với trình kích hoạt mặc định thường yêu cầu phải có toàn bộ tập dữ liệu trước khi xử lý, điều này không thể thực hiện được với dữ liệu cập nhật liên tục. To perform aggregations on an unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that uses global windowing, you should specify a non-default trigger for that
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

8. 3. Setting your PCollection’s windowing function

You can set the windowing function for a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by applying the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
244 transform. When you apply the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
244 transform, you must provide a
--=
45. The
--=
45 determines the windowing function your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 will use for subsequent grouping transforms, such as a fixed or sliding time window

When you set a windowing function, you may also want to set a trigger for your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The trigger determines when each individual window is aggregated and emitted, and helps refine how the windowing function performs with respect to late data and computing early results. See the section for more information

8. 3. 1. Fixed-time windows

The following example code shows how to apply

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
244 to divide a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into fixed windows, each 60 seconds in length

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
20

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
21

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
22

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
23

8. 3. 2. Sliding time windows

The following example code shows how to apply

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
244 to divide a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into sliding time windows. Each window is 30 seconds in length, and a new window begins every five seconds

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
24

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
25

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
26

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
27

8. 3. 3. Session windows

The following example code shows how to apply

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
244 to divide a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into session windows, where each session must be separated by a time gap of at least 10 minutes [600 seconds]

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
28

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
29

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
30

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
31

Lưu ý rằng các phiên là theo từng khóa — mỗi khóa trong bộ sưu tập sẽ có các nhóm phiên riêng tùy thuộc vào phân phối dữ liệu

8. 3. 4. Cửa sổ toàn cầu duy nhất

Nếu

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn bị giới hạn [kích thước cố định], bạn có thể gán tất cả các thành phần cho một cửa sổ chung duy nhất. Mã ví dụ sau đây cho biết cách đặt một cửa sổ chung duy nhất cho một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
32

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
33

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
34

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
35

8. 4. Hình mờ và dữ liệu muộn

Trong bất kỳ hệ thống xử lý dữ liệu nào, có một độ trễ nhất định giữa thời điểm một sự kiện dữ liệu xảy ra ["thời gian sự kiện", được xác định bởi dấu thời gian trên chính phần tử dữ liệu] và thời gian phần tử dữ liệu thực tế được xử lý ở bất kỳ giai đoạn nào trong . Ngoài ra, không có gì đảm bảo rằng các sự kiện dữ liệu sẽ xuất hiện trong quy trình bán hàng của bạn theo đúng thứ tự mà chúng được tạo

Ví dụ: giả sử chúng ta có một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 đang sử dụng cửa sổ có thời gian cố định, với các cửa sổ dài năm phút. Đối với mỗi cửa sổ, Beam phải thu thập tất cả dữ liệu có dấu thời gian của sự kiện trong phạm vi cửa sổ nhất định [từ 0. 00 và 4. 59 trong cửa sổ đầu tiên chẳng hạn]. Dữ liệu có dấu thời gian nằm ngoài phạm vi đó [dữ liệu từ 5. 00 trở lên] thuộc về một cửa sổ khác

Tuy nhiên, dữ liệu không phải lúc nào cũng được đảm bảo đến theo một đường ống theo thứ tự thời gian hoặc luôn đến theo các khoảng thời gian có thể dự đoán được. Beam theo dõi một hình mờ, đó là khái niệm của hệ thống về thời điểm tất cả dữ liệu trong một cửa sổ nhất định có thể được đưa vào đường ống. Sau khi hình mờ đi qua cuối cửa sổ, bất kỳ phần tử nào khác xuất hiện cùng với dấu thời gian trong cửa sổ đó đều được coi là dữ liệu muộn

Từ ví dụ của chúng tôi, giả sử chúng tôi có một hình mờ đơn giản giả định thời gian trễ khoảng 30 giây giữa dấu thời gian dữ liệu [thời gian sự kiện] và thời gian dữ liệu xuất hiện trong đường ống [thời gian xử lý], sau đó Beam sẽ đóng cửa sổ đầu tiên ở mức 5. 30. Nếu một bản ghi dữ liệu đến lúc 5. 34, nhưng với dấu thời gian sẽ đưa nó vào 0. 00-4. 59 cửa sổ [giả sử, 3. 38], thì bản ghi đó là dữ liệu trễ

Ghi chú. Để đơn giản, chúng tôi giả định rằng chúng tôi đang sử dụng một hình mờ rất đơn giản để ước tính thời gian trễ. Trên thực tế, nguồn dữ liệu của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn xác định hình mờ và hình mờ có thể chính xác hoặc phức tạp hơn

Cấu hình cửa sổ mặc định của Beam cố gắng xác định thời điểm tất cả dữ liệu đã đến [dựa trên loại nguồn dữ liệu] và sau đó chuyển hình mờ qua cuối cửa sổ. Cấu hình mặc định này không cho phép dữ liệu trễ. cho phép bạn sửa đổi và tinh chỉnh chiến lược cửa sổ cho một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Bạn có thể sử dụng trình kích hoạt để quyết định thời điểm mỗi cửa sổ riêng lẻ tổng hợp và báo cáo kết quả của nó, bao gồm cả cách cửa sổ phát ra các phần tử muộn

8. 4. 1. Quản lý dữ liệu muộn

Bạn có thể cho phép dữ liệu trễ bằng cách gọi hoạt động ________ 45 ______ 308 khi bạn đặt chiến lược cửa sổ của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Ví dụ mã sau minh họa chiến lược tạo cửa sổ sẽ cho phép dữ liệu trễ tối đa hai ngày sau khi kết thúc cửa sổ

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
36

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
37

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
38

When you set

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
308 on a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, that allowed lateness propagates forward to any subsequent
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 derived from the first
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 you applied allowed lateness to. Nếu bạn muốn thay đổi độ trễ được phép sau này trong quy trình bán hàng của mình, bạn phải làm như vậy một cách rõ ràng bằng cách áp dụng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
314

8. 5. Thêm dấu thời gian vào các phần tử của PCollection

Nguồn không giới hạn cung cấp dấu thời gian cho từng phần tử. Tùy thuộc vào nguồn không giới hạn của bạn, bạn có thể cần định cấu hình cách trích xuất dấu thời gian từ luồng dữ liệu thô

Tuy nhiên, các nguồn có giới hạn [chẳng hạn như tệp từ

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
258] không cung cấp dấu thời gian. Nếu bạn cần dấu thời gian, bạn phải thêm chúng vào các phần tử của
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

Bạn có thể gán dấu thời gian mới cho các phần tử của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách áp dụng một biến đổi tạo ra các phần tử mới với dấu thời gian mà bạn đã đặt

Một ví dụ có thể là nếu quy trình của bạn đọc các bản ghi nhật ký từ một tệp đầu vào và mỗi bản ghi nhật ký bao gồm một trường dấu thời gian; . Bạn có thể phân tích cú pháp trường dấu thời gian từ mỗi bản ghi và sử dụng biến đổi

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 với
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 để đính kèm dấu thời gian vào từng thành phần trong
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
39

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
40

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
41

9. Gây nên

Ghi chú. API kích hoạt trong Beam SDK for Go hiện đang thử nghiệm và có thể thay đổi

Khi thu thập và nhóm dữ liệu vào các cửa sổ, Beam sử dụng trình kích hoạt để xác định thời điểm phát ra kết quả tổng hợp của từng cửa sổ [được gọi là ngăn]. Nếu bạn sử dụng cấu hình cửa sổ mặc định của Beam và , Beam sẽ xuất kết quả tổng hợp khi nó và loại bỏ tất cả dữ liệu tiếp theo cho cửa sổ đó

You can set triggers for your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s to change this default behavior. Beam provides a number of pre-built triggers that you can set

  • Trình kích hoạt thời gian sự kiện. Các trình kích hoạt này hoạt động theo thời gian của sự kiện, như được biểu thị bằng dấu thời gian trên mỗi phần tử dữ liệu. Trình kích hoạt mặc định của Beam dựa trên thời gian của sự kiện
  • Kích hoạt thời gian xử lý. Các trình kích hoạt này hoạt động theo thời gian xử lý – thời điểm phần tử dữ liệu được xử lý ở bất kỳ giai đoạn cụ thể nào trong quy trình
  • Trình kích hoạt theo hướng dữ liệu. Các trình kích hoạt này hoạt động bằng cách kiểm tra dữ liệu khi dữ liệu đến trong mỗi cửa sổ và kích hoạt khi dữ liệu đó đáp ứng một thuộc tính nhất định. Hiện tại, trình kích hoạt theo hướng dữ liệu chỉ hỗ trợ kích hoạt sau một số phần tử dữ liệu nhất định
  • kích hoạt tổng hợp. Các trình kích hoạt này kết hợp nhiều trình kích hoạt theo nhiều cách khác nhau

Ở cấp độ cao, trình kích hoạt cung cấp hai khả năng bổ sung so với việc chỉ xuất ra ở cuối cửa sổ

  • Trình kích hoạt cho phép Beam phát ra kết quả sớm, trước khi tất cả dữ liệu trong một cửa sổ nhất định đến. Ví dụ: phát ra sau một khoảng thời gian nhất định hoặc sau khi một số phần tử nhất định đến
  • Trình kích hoạt cho phép xử lý dữ liệu muộn bằng cách kích hoạt sau khi hình mờ thời gian sự kiện đi qua cuối cửa sổ

Những khả năng này cho phép bạn kiểm soát luồng dữ liệu của mình và cân bằng giữa các yếu tố khác nhau tùy thuộc vào trường hợp sử dụng của bạn

  • sự hoàn chỉnh. Việc có tất cả dữ liệu trước khi tính toán kết quả quan trọng như thế nào?
  • Latency. Bạn muốn chờ dữ liệu trong bao lâu?
  • Phí tổn. Bạn sẵn sàng chi bao nhiêu tiền/sức mạnh tính toán để giảm độ trễ?

Ví dụ: một hệ thống yêu cầu các bản cập nhật nhạy cảm với thời gian có thể sử dụng trình kích hoạt dựa trên thời gian nghiêm ngặt phát ra một cửa sổ sau mỗi N giây, đánh giá tính kịp thời hơn tính đầy đủ của dữ liệu. Một hệ thống coi trọng tính đầy đủ của dữ liệu hơn thời gian chính xác của kết quả có thể chọn sử dụng trình kích hoạt mặc định của Beam, kích hoạt ở cuối cửa sổ

Bạn cũng có thể đặt trình kích hoạt cho một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn sử dụng một. Điều này có thể hữu ích khi bạn muốn quy trình của mình cung cấp các bản cập nhật định kỳ trên tập dữ liệu không giới hạn — ví dụ: mức trung bình đang chạy của tất cả dữ liệu được cung cấp cho thời điểm hiện tại, được cập nhật N giây hoặc mỗi N phần tử

9. 1. Trình kích hoạt thời gian sự kiện

Trình kích hoạt

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
323 hoạt động vào thời gian diễn ra sự kiện. Trình kích hoạt
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
323 phát ra nội dung của một cửa sổ sau khi vượt qua phần cuối của cửa sổ, dựa trên dấu thời gian được đính kèm với các thành phần dữ liệu. Hình mờ là thước đo tiến độ toàn cầu và là khái niệm của Beam về tính đầy đủ của đầu vào trong quy trình của bạn tại bất kỳ điểm nào. ______45_______325 ______45_______323
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
327
chỉ kích hoạt khi hình mờ đi qua cuối cửa sổ.

Ngoài ra, bạn có thể định cấu hình trình kích hoạt kích hoạt nếu quy trình của bạn nhận dữ liệu trước hoặc sau khi kết thúc cửa sổ

Ví dụ sau đây cho thấy một kịch bản thanh toán và sử dụng cả kích hoạt sớm và muộn

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
42

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
43

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
44

9. 1. 1. Trình kích hoạt mặc định

Trình kích hoạt mặc định cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 dựa trên thời gian sự kiện và phát ra kết quả của cửa sổ khi hình mờ của Tia đi qua cuối cửa sổ, sau đó kích hoạt mỗi khi dữ liệu trễ đến

Tuy nhiên, nếu bạn đang sử dụng cả cấu hình cửa sổ mặc định và trình kích hoạt mặc định, trình kích hoạt mặc định sẽ phát chính xác một lần và dữ liệu muộn sẽ bị loại bỏ. Điều này là do cấu hình cửa sổ mặc định có giá trị độ trễ cho phép là 0. Xem phần Xử lý dữ liệu muộn để biết thông tin về cách sửa đổi hành vi này

9. 2. Kích hoạt thời gian xử lý

Trình kích hoạt

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
329 hoạt động theo thời gian xử lý. Ví dụ: trình kích hoạt ______45_______330 ______45_______329
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
332
phát ra một cửa sổ sau một khoảng thời gian nhất định . Thời gian xử lý được xác định bởi đồng hồ hệ thống, thay vì dấu thời gian của phần tử dữ liệu.

Trình kích hoạt

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
329 hữu ích để kích hoạt kết quả sớm từ một cửa sổ, đặc biệt là cửa sổ có khung thời gian lớn, chẳng hạn như một cửa sổ toàn cầu

9. 3. Trình kích hoạt theo hướng dữ liệu

Beam cung cấp một trình kích hoạt theo hướng dữ liệu,

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
334
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
335
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
336
. This trigger works on an element count; it fires after the current pane has collected at least N elements. This allows a window to emit early results [before all the data has accumulated], which can be particularly useful if you are using a single global window.

Ví dụ: điều quan trọng cần lưu ý là nếu bạn chỉ định ______45_______337 afterCount[50] . Nếu 32 yếu tố quan trọng với bạn, hãy cân nhắc sử dụng để kết hợp nhiều điều kiện. Điều này cho phép bạn chỉ định nhiều điều kiện bắn, chẳng hạn như “bắn khi tôi nhận được 50 phần tử hoặc cứ sau 1 giây”. and only 32 elements arrive, those 32 elements sit around forever. If the 32 elements are important to you, consider using to combine multiple conditions. This allows you to specify multiple firing conditions such as “fire either when I receive 50 elements, or every 1 second”.

9. 4. Đặt trình kích hoạt

Khi bạn đặt chức năng tạo cửa sổ cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách sử dụng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
244
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
341
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
342
transform, you can also specify a trigger.

Bạn đặt [các] trình kích hoạt cho một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách gọi phương thức
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
344 dựa trên kết quả biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
345 của bạn. Mẫu mã này đặt trình kích hoạt dựa trên thời gian cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, trình kích hoạt này đưa ra kết quả một phút sau khi phần tử đầu tiên trong cửa sổ đó được xử lý. The last line in the code sample,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
347, sets the window’s accumulation mode

Bạn đặt [các] trình kích hoạt cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách đặt tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
349 khi bạn sử dụng biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
341. Mẫu mã này đặt trình kích hoạt dựa trên thời gian cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, trình kích hoạt này đưa ra kết quả một phút sau khi phần tử đầu tiên trong cửa sổ đó được xử lý. Tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
352 đặt chế độ tích lũy của cửa sổ

Bạn đặt [các] trình kích hoạt cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách chuyển tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
354 khi bạn sử dụng biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
342. Mẫu mã này đặt trình kích hoạt dựa trên thời gian cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, trình kích hoạt này đưa ra kết quả một phút sau khi phần tử đầu tiên trong cửa sổ đó được xử lý. Tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
357 đặt chế độ tích lũy của cửa sổ

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
45

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
46

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
47

9. 4. 1. Chế độ tích lũy cửa sổ

Khi bạn chỉ định trình kích hoạt, bạn cũng phải đặt chế độ tích lũy của cửa sổ. Khi trình kích hoạt kích hoạt, nó sẽ phát ra nội dung hiện tại của cửa sổ dưới dạng một ngăn. Vì trình kích hoạt có thể kích hoạt nhiều lần, nên chế độ tích lũy sẽ xác định xem hệ thống sẽ tích lũy các ô cửa sổ khi trình kích hoạt kích hoạt hay loại bỏ chúng

Để đặt một cửa sổ tích lũy các ô được tạo khi trình kích hoạt kích hoạt, hãy gọi_______45_______358 khi bạn đặt kích hoạt. Để đặt một cửa sổ loại bỏ các ô đã bắn, hãy gọi

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
347

Để đặt một cửa sổ tích lũy các ô được tạo khi kích hoạt kích hoạt, hãy đặt tham số

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
352 thành
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
361 khi bạn đặt kích hoạt. Để đặt một cửa sổ loại bỏ các tấm đã nung, hãy đặt
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
352 thành
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
363

To set a window to accumulate the panes that are produced when the trigger fires, set the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
357 parameter to
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
365 when you set the trigger. Để đặt một cửa sổ loại bỏ các ô đã nung, hãy đặt
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
357 thành
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
367

Hãy xem một ví dụ sử dụng

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 với cửa sổ thời gian cố định và trình kích hoạt dựa trên dữ liệu. Đây là điều bạn có thể làm nếu, ví dụ: mỗi cửa sổ biểu thị mức trung bình đang chạy trong mười phút, nhưng bạn muốn hiển thị giá trị hiện tại của mức trung bình trong giao diện người dùng thường xuyên hơn mười phút một lần. Chúng tôi sẽ giả định các điều kiện sau đây

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 sử dụng cửa sổ thời gian cố định 10 phút
  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 có trình kích hoạt lặp lại sẽ kích hoạt mỗi khi 3 phần tử đến

Sơ đồ sau hiển thị các sự kiện dữ liệu cho khóa X khi chúng đến PCollection và được gán cho các cửa sổ. Để sơ đồ đơn giản hơn một chút, chúng ta sẽ giả định rằng tất cả các sự kiện đều đến trong quy trình theo thứ tự

9. 4. 1. 1. chế độ tích lũy

Nếu trình kích hoạt của chúng tôi được đặt ở chế độ tích lũy, thì trình kích hoạt sẽ phát ra các giá trị sau mỗi lần kích hoạt. Hãy nhớ rằng trình kích hoạt sẽ kích hoạt mỗi khi ba yếu tố đến

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
489. 4. 1. 2. chế độ loại bỏ

Nếu trình kích hoạt của chúng tôi được đặt ở chế độ loại bỏ, trình kích hoạt sẽ phát ra các giá trị sau trên mỗi lần kích hoạt

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
49

9. 4. 2. Xử lý dữ liệu muộn

Nếu bạn muốn quy trình của mình xử lý dữ liệu đến sau khi hình mờ đi qua cuối cửa sổ, bạn có thể áp dụng độ trễ cho phép khi đặt cấu hình cửa sổ của mình. Điều này giúp trình kích hoạt của bạn có cơ hội phản ứng với dữ liệu muộn. If allowed lateness is set, the default trigger will emit new results immediately whenever late data arrives

Bạn đặt độ trễ cho phép bằng cách sử dụng ______45_______371

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
372
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
373
when you set your windowing function:

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
50

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
51

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
52

Độ trễ cho phép này lan truyền đến tất cả các

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có được do áp dụng các biến đổi cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 ban đầu. Nếu bạn muốn thay đổi độ trễ được phép sau này trong quy trình bán hàng của mình, bạn có thể đăng ký
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
314
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
372
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
373
again, explicitly.

9. 5. kích hoạt tổng hợp

Bạn có thể kết hợp nhiều trình kích hoạt để tạo thành trình kích hoạt tổng hợp và có thể chỉ định trình kích hoạt để phát ra kết quả nhiều lần, nhiều nhất một lần hoặc trong các điều kiện tùy chỉnh khác

9. 5. 1. Các loại kích hoạt tổng hợp

Beam bao gồm các kích hoạt tổng hợp sau

  • Bạn có thể thêm các lần kích hoạt sớm hoặc kích hoạt muộn bổ sung cho
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    379 qua
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    380 và
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    381
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    382 chỉ định trình kích hoạt thực thi mãi mãi. Bất cứ khi nào các điều kiện của trình kích hoạt được đáp ứng, nó sẽ khiến một cửa sổ phát ra kết quả rồi đặt lại và bắt đầu lại. Có thể hữu ích khi kết hợp
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    382 với
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    384 để chỉ định một điều kiện khiến trình kích hoạt lặp lại dừng lại
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    385 kết hợp nhiều kích hoạt để kích hoạt theo một trình tự cụ thể. Each time a trigger in the sequence emits a window, the sequence advances to the next trigger
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    386 nhận nhiều trình kích hoạt và phát ra lần đầu tiên bất kỳ trình kích hoạt đối số nào của nó được thỏa mãn. Điều này tương đương với phép toán OR logic cho nhiều trình kích hoạt
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    387 nhận nhiều trình kích hoạt và phát ra khi tất cả các trình kích hoạt đối số của nó được thỏa mãn. Điều này tương đương với phép toán AND logic cho nhiều trình kích hoạt
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    388 có thể đóng vai trò là điều kiện cuối cùng để khiến bất kỳ cò súng nào kích hoạt lần cuối và không bao giờ kích hoạt nữa

9. 5. 2. Thành phần với AfterWatermark

Một số trình kích hoạt tổng hợp hữu ích nhất kích hoạt một lần duy nhất khi Beam ước tính rằng tất cả dữ liệu đã đến [i. e. khi hình mờ đi qua cuối cửa sổ] kết hợp với một trong hai hoặc cả hai điều sau

  • Các lần kích hoạt đầu cơ trước khi hình mờ đi qua cuối cửa sổ để cho phép xử lý một phần kết quả nhanh hơn

  • Các lần kích hoạt muộn xảy ra sau khi hình mờ đi qua cuối cửa sổ, để cho phép xử lý dữ liệu đến muộn

Bạn có thể diễn đạt mẫu này bằng cách sử dụng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
323. Ví dụ: mã kích hoạt ví dụ sau kích hoạt trong các điều kiện sau

  • Theo ước tính của Beam, tất cả dữ liệu đã đến [hình mờ vượt qua cuối cửa sổ]

  • Bất cứ lúc nào dữ liệu đến trễ, sau mười phút chậm trễ

  • Sau hai ngày, chúng tôi cho rằng sẽ không có thêm dữ liệu quan tâm nào đến và trình kích hoạt sẽ ngừng thực thi

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
53

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
54

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
55

9. 5. 3. Other composite triggers

You can also build other sorts of composite triggers. Mã ví dụ sau hiển thị trình kích hoạt tổng hợp đơn giản kích hoạt bất cứ khi nào ngăn có ít nhất 100 phần tử hoặc sau một phút

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
56

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
57

10. số liệu

Trong mô hình Beam, các chỉ số cung cấp một số thông tin chi tiết về trạng thái hiện tại của quy trình người dùng, có thể xảy ra trong khi quy trình đang chạy. Có thể có những lý do khác nhau cho điều đó, ví dụ

  • Kiểm tra số lỗi gặp phải khi chạy một bước cụ thể trong quy trình;
  • Theo dõi số lượng RPC được thực hiện cho dịch vụ phụ trợ;
  • Truy xuất số lượng chính xác số lượng phần tử đã được xử lý;
  • …và như thế

10. 1. Các khái niệm chính về chỉ số Beam

  • được đặt tên. Mỗi chỉ số có một tên bao gồm một không gian tên và một tên thực tế. Không gian tên có thể được sử dụng để phân biệt giữa nhiều chỉ số có cùng tên và cũng cho phép truy vấn tất cả các chỉ số trong một không gian tên cụ thể
  • phạm vi. Mỗi số liệu được báo cáo theo một bước cụ thể trong quy trình bán hàng, cho biết mã nào đang chạy khi số liệu đó tăng lên
  • Dynamically Created. Các chỉ số có thể được tạo trong thời gian chạy mà không cần khai báo trước chúng, giống như cách tạo một trình ghi nhật ký. Điều này giúp tạo ra các số liệu trong mã tiện ích dễ dàng hơn và báo cáo chúng một cách hữu ích
  • xuống cấp một cách duyên dáng. Nếu một người chạy không hỗ trợ một số phần của báo cáo chỉ số, thì hành vi dự phòng là bỏ cập nhật chỉ số thay vì làm hỏng quy trình. Nếu một trình chạy không hỗ trợ một số phần của số liệu truy vấn, thì trình chạy sẽ không trả về dữ liệu được liên kết

Các chỉ số được báo cáo hoàn toàn nằm trong phạm vi biến đổi trong quy trình đã báo cáo các chỉ số đó. Điều này cho phép báo cáo cùng một tên chỉ số ở nhiều nơi và xác định giá trị mà mỗi biến đổi được báo cáo, cũng như tổng hợp chỉ số trên toàn bộ quy trình

Ghi chú. Việc các số liệu có thể truy cập được trong quá trình thực thi đường ống hay chỉ sau khi các công việc đã hoàn thành là phụ thuộc vào người chạy.

10. 2. Các loại chỉ số

Có ba loại số liệu được hỗ trợ tại thời điểm này.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
390,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
391 và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
392

Trong Beam SDK for Go, một

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
13 do khung cung cấp phải được chuyển đến chỉ số, nếu không giá trị chỉ số sẽ không được ghi lại. Khung sẽ tự động cung cấp một ____64_______13 hợp lệ cho ____56_______39 và các phương thức tương tự khi đó là tham số đầu tiên

Phản đối. Số liệu báo cáo một giá trị dài duy nhất và có thể tăng hoặc giảm

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
58

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
59

Phân bổ. Một số liệu báo cáo thông tin về việc phân phối các giá trị được báo cáo

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
60

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
61

máy đo. Số liệu báo cáo giá trị mới nhất trong số các giá trị được báo cáo. Vì các số liệu được thu thập từ nhiều công nhân nên giá trị có thể không phải là giá trị cuối cùng tuyệt đối mà là một trong những giá trị mới nhất

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
62

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
63

10. 3. Số liệu truy vấn

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
396 có phương thức
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
397 trả về đối tượng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
398 cho phép truy cập số liệu. Phương thức chính có sẵn trong
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
398 cho phép truy vấn tất cả các chỉ số phù hợp với một bộ lọc nhất định

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
400 có một phương thức
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
401 trả về một đối tượng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
402 cho phép truy cập các số liệu. Phương pháp chính có sẵn trong
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
402 cho phép truy vấn tất cả các chỉ số phù hợp với một bộ lọc nhất định. Nó nhận một vị ngữ có loại tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
404, có thể được sử dụng cho các bộ lọc tùy chỉnh

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
64

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
65

10. 4. Sử dụng số liệu trong quy trình

Bên dưới, có một ví dụ đơn giản về cách sử dụng chỉ số

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
390 trong quy trình người dùng

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
66

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
67

10. 5. Xuất chỉ số

Số liệu chùm tia có thể được xuất sang các phần chìm bên ngoài. Nếu một số liệu chìm được thiết lập trong cấu hình, người chạy sẽ đẩy các số liệu tới nó trong khoảng thời gian 5 giây mặc định. Cấu hình được giữ trong lớp MetricsOptions. Nó chứa cấu hình thời gian đẩy và cũng có các tùy chọn cụ thể chìm như loại và URL. Hiện tại, chỉ có REST HTTP và các phần chìm Graphite được hỗ trợ và chỉ các trình chạy Flink và Spark hỗ trợ xuất số liệu

Ngoài ra, các số liệu Beam được xuất sang bảng điều khiển Spark và Flink bên trong để được tư vấn trong giao diện người dùng tương ứng của chúng

11. Trạng thái và bộ hẹn giờ

Các cơ sở kích hoạt và cửa sổ của Beam cung cấp khả năng trừu tượng hóa mạnh mẽ để nhóm và tổng hợp dữ liệu đầu vào không giới hạn dựa trên dấu thời gian. Tuy nhiên, có những trường hợp sử dụng tổng hợp mà các nhà phát triển có thể yêu cầu mức độ kiểm soát cao hơn mức độ kiểm soát được cung cấp bởi các cửa sổ và trình kích hoạt. Beam provides an API for manually managing per-key state, allowing for fine-grained control over aggregations

Trạng thái mô hình API trạng thái của Beam trên mỗi khóa. Để sử dụng API trạng thái, bạn bắt đầu với một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có khóa, trong Java được mô hình hóa như một
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
13. Một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 đang xử lý
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 này hiện có thể khai báo các biến trạng thái. Bên trong
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, các biến trạng thái này có thể được sử dụng để ghi hoặc cập nhật trạng thái cho khóa hiện tại hoặc để đọc trạng thái trước đó được ghi cho khóa đó. Trạng thái luôn chỉ nằm trong phạm vi đầy đủ đối với khóa xử lý hiện tại

Cửa sổ vẫn có thể được sử dụng cùng với xử lý trạng thái. Tất cả trạng thái cho một khóa nằm trong phạm vi cửa sổ hiện tại. Điều này có nghĩa là lần đầu tiên một khóa được nhìn thấy cho một cửa sổ nhất định, bất kỳ trạng thái nào được đọc sẽ trả về trống và một trình chạy có thể thu gom rác trạng thái khi một cửa sổ hoàn thành. Nó cũng thường hữu ích khi sử dụng các tập hợp cửa sổ của Beam trước toán tử trạng thái. Ví dụ: sử dụng bộ kết hợp để tổng hợp trước dữ liệu, sau đó lưu trữ dữ liệu đã tổng hợp bên trong trạng thái. Các cửa sổ hợp nhất hiện không được hỗ trợ khi sử dụng trạng thái và bộ hẹn giờ

Đôi khi xử lý trạng thái được sử dụng để triển khai xử lý kiểu máy trạng thái bên trong một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. Khi thực hiện việc này, cần lưu ý rằng các phần tử trong PCCollection đầu vào không có thứ tự được đảm bảo và để đảm bảo rằng logic chương trình có khả năng phục hồi theo điều này. Các bài kiểm tra đơn vị được viết bằng DirectRunner sẽ xáo trộn thứ tự xử lý phần tử và được khuyến nghị để kiểm tra tính chính xác

Trong Java, DoFn tuyên bố các trạng thái sẽ được truy cập bằng cách tạo các biến thành viên

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
412 cuối cùng đại diện cho mỗi trạng thái. Mỗi tiểu bang phải được đặt tên bằng cách sử dụng chú thích
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
413; . Một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 có thể khai báo nhiều biến trạng thái

In Python, DoFn declares states to be accessed by creating

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
412 class member variables representing each state. Mỗi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
412 được khởi tạo bằng một tên, tên này là duy nhất cho một ParDo trong biểu đồ và không liên quan đến các nút khác trong biểu đồ. Một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 có thể khai báo nhiều biến trạng thái

Trong Go, DoFn khai báo các trạng thái sẽ được truy cập bằng cách tạo các biến thành viên cấu trúc trạng thái đại diện cho từng trạng thái. Mỗi biến trạng thái được khởi tạo bằng một khóa, khóa này là duy nhất cho một ParDo trong biểu đồ và không liên quan đến các nút khác trong biểu đồ. Nếu không cung cấp tên, khóa sẽ mặc định là tên của biến thành viên. Một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 có thể khai báo nhiều biến trạng thái

Ghi chú. Beam SDK cho Bản mô tả chưa hỗ trợ API Trạng thái và Hẹn giờ, nhưng có thể sử dụng các tính năng này từ các đường dẫn ngôn ngữ chéo [xem bên dưới]

11. 1. Các loại trạng thái

Beam cung cấp một số loại trạng thái

ValueState

ValueState là một giá trị trạng thái vô hướng. Đối với mỗi khóa trong đầu vào, một ValueState sẽ lưu trữ một giá trị đã nhập có thể được đọc và sửa đổi bên trong các phương thức

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 hoặc
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
44 của DoFn. Nếu loại ValueState có bộ mã hóa được đăng ký, thì Beam sẽ tự động suy ra bộ mã hóa cho giá trị trạng thái. Mặt khác, một bộ mã hóa có thể được chỉ định rõ ràng khi tạo ValueState. Ví dụ: ParDo sau đây tạo một biến trạng thái duy nhất tích lũy số lượng phần tử được nhìn thấy

Ghi chú.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
421 is called
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
422 in the Python SDK

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
68

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
69

Beam cũng cho phép chỉ định rõ ràng một bộ mã hóa cho các giá trị

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
421. Ví dụ

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
70

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
71

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
72

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
73

Kết hợpTrạng thái

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
424 cho phép bạn tạo một đối tượng trạng thái được cập nhật bằng bộ kết hợp Beam. Ví dụ: ví dụ
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
421 trước đó có thể được viết lại để sử dụng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
424

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
74

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
75

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
76

TúiBang

Một trường hợp sử dụng phổ biến cho trạng thái là tích lũy nhiều phần tử.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
427 cho phép tích lũy một tập hợp các phần tử không có thứ tự. Điều này cho phép thêm các phần tử vào bộ sưu tập mà không yêu cầu đọc toàn bộ bộ sưu tập trước, đây là một hiệu quả đạt được. In addition, runners that support paged reads can allow individual bags larger than available memory

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
77

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
78

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
35

11. 2. Đọc trạng thái hoãn lại

Khi một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 chứa nhiều thông số trạng thái, việc đọc từng thông số theo thứ tự có thể chậm. Gọi hàm
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
429 trên một trạng thái có thể khiến người chạy thực hiện thao tác chặn đọc. Thực hiện nhiều lần đọc chặn theo trình tự sẽ thêm độ trễ cho quá trình xử lý phần tử. Nếu bạn biết rằng một trạng thái sẽ luôn được đọc, bạn có thể chú thích trạng thái đó là @AlwaysFetched, sau đó trình chạy có thể tìm nạp trước tất cả các trạng thái cần thiết. Ví dụ

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
80

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
81

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
82

Tuy nhiên, nếu có các đường dẫn mã trong đó các trạng thái không được tìm nạp, thì việc chú thích bằng @AlwaysFetched sẽ thêm tính năng tìm nạp không cần thiết cho các đường dẫn đó. Trong trường hợp này, phương thức readLater cho phép người chạy biết rằng trạng thái sẽ được đọc trong tương lai, cho phép nhiều lần đọc trạng thái được gộp lại với nhau

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
83

11. 3. hẹn giờ

Beam cung cấp API gọi lại hẹn giờ cho mỗi phím. This allows for delayed processing of data stored using the state API. Bộ hẹn giờ có thể được đặt thành gọi lại tại thời điểm sự kiện hoặc dấu thời gian xử lý. Mỗi bộ đếm thời gian được xác định bằng TimerId. Chỉ có thể đặt bộ hẹn giờ nhất định cho một phím cho một dấu thời gian. Cuộc gọi được đặt trên bộ hẹn giờ sẽ ghi đè thời gian kích hoạt trước đó cho bộ hẹn giờ của phím đó

11. 3. 1. bộ hẹn giờ sự kiện

Bộ hẹn giờ thời gian sự kiện kích hoạt khi hình mờ đầu vào cho DoFn vượt qua thời gian mà bộ hẹn giờ được đặt, nghĩa là người chạy tin rằng không có thêm yếu tố nào được xử lý bằng dấu thời gian trước dấu thời gian của bộ hẹn giờ. Điều này cho phép tổng hợp thời gian sự kiện

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
84

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
85

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 3. 2. bộ định thời gian xử lý

Bộ hẹn giờ thời gian xử lý kích hoạt khi thời gian thực của đồng hồ treo tường trôi qua. Điều này thường được sử dụng để tạo các lô dữ liệu lớn hơn trước khi xử lý. Nó cũng có thể được sử dụng để lên lịch các sự kiện sẽ xảy ra vào một thời điểm cụ thể. Cũng giống như với bộ hẹn giờ thời gian sự kiện, bộ hẹn giờ thời gian xử lý là trên mỗi khóa - mỗi khóa có một bản sao riêng của bộ hẹn giờ

Mặc dù bộ hẹn giờ thời gian xử lý có thể được đặt thành dấu thời gian tuyệt đối, nhưng rất phổ biến để đặt chúng thành phần bù so với thời gian hiện tại. In Java, the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
430 and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
431 methods can be used to accomplish this

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
87

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
88

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 3. 3. Thẻ hẹn giờ động

Beam cũng hỗ trợ tự động thiết lập thẻ hẹn giờ bằng cách sử dụng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
432 trong SDK Java. Điều này cho phép cài đặt nhiều bộ hẹn giờ khác nhau trong một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 và cho phép chọn động các thẻ bộ hẹn giờ - e. g. dựa trên dữ liệu trong các yếu tố đầu vào. Chỉ có thể đặt bộ hẹn giờ với một thẻ cụ thể thành một dấu thời gian duy nhất, do đó, việc đặt lại bộ hẹn giờ có tác dụng ghi đè thời gian hết hạn trước đó cho bộ hẹn giờ với thẻ đó. Mỗi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
432 được xác định bằng id họ bộ hẹn giờ và các bộ hẹn giờ trong các họ bộ hẹn giờ khác nhau là độc lập

Trong SDK Python, thẻ hẹn giờ động có thể được chỉ định trong khi gọi

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
435 hoặc
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
436. Theo mặc định, thẻ hẹn giờ là một chuỗi rỗng nếu không được chỉ định

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
90

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
91

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 3. 4. Dấu thời gian đầu ra của bộ hẹn giờ

Theo mặc định, bộ hẹn giờ theo thời gian sự kiện sẽ giữ hình mờ đầu ra của

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 cho dấu thời gian của bộ hẹn giờ. Điều này có nghĩa là nếu bộ hẹn giờ được đặt thành 12 giờ đêm, thì bất kỳ tập hợp cửa sổ hoặc bộ hẹn giờ sự kiện nào sau này trong biểu đồ quy trình kết thúc sau 12 giờ đêm sẽ không hết hạn. The timestamp of the timer is also the default output timestamp for the timer callback. Điều này có nghĩa là bất kỳ phần tử nào xuất ra từ phương thức onTimer sẽ có dấu thời gian bằng với dấu thời gian của bộ hẹn giờ kích hoạt. Đối với bộ hẹn giờ thời gian xử lý, dấu thời gian đầu ra mặc định và giữ hình mờ là giá trị của hình mờ đầu vào tại thời điểm bộ hẹn giờ được đặt

Trong một số trường hợp, DoFn cần xuất dấu thời gian sớm hơn thời gian hết hạn của bộ hẹn giờ và do đó cũng cần giữ hình mờ đầu ra của nó đối với các dấu thời gian đó. Ví dụ: hãy xem xét quy trình sau tạm thời nhóm các bản ghi vào trạng thái và đặt bộ hẹn giờ để thoát trạng thái. Mã này có thể xuất hiện đúng, nhưng sẽ không hoạt động bình thường

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
93

Vấn đề với mã này là ParDo đang đệm các phần tử, tuy nhiên không có gì ngăn hình mờ vượt qua dấu thời gian của các phần tử đó, vì vậy tất cả các phần tử đó có thể bị loại bỏ dưới dạng dữ liệu muộn. Để ngăn điều này xảy ra, dấu thời gian đầu ra cần được đặt trên bộ hẹn giờ để ngăn hình mờ vượt qua dấu thời gian của phần tử tối thiểu. Đoạn mã sau chứng minh điều này

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
94

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
95

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 4. Tình trạng thu gom rác

Trạng thái trên mỗi khóa cần được thu gom rác hoặc cuối cùng kích thước ngày càng tăng của trạng thái có thể tác động tiêu cực đến hiệu suất. Có hai chiến lược phổ biến cho trạng thái thu gom rác

11. 4. 1. Sử dụng cửa sổ để thu gom rác

Tất cả trạng thái và bộ hẹn giờ cho một khóa nằm trong phạm vi cửa sổ chứa khóa đó. This means that depending on the timestamp of the input element the ParDo will see different values for the state depending on the window that element falls into. Ngoài ra, khi hình mờ đầu vào đi qua cuối cửa sổ, trình chạy sẽ thu thập tất cả trạng thái cho cửa sổ đó. [Ghi chú. nếu độ trễ cho phép được đặt thành giá trị dương cho cửa sổ, người chạy phải đợi hình mờ đi qua cuối cửa sổ cộng với độ trễ cho phép trước trạng thái thu gom rác]. Điều này có thể được sử dụng như một chiến lược thu gom rác

Ví dụ, được đưa ra sau đây

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
97

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
98

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
99

Trạng thái cửa hàng

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 này mỗi ngày. Khi đường ống xử lý xong dữ liệu cho một ngày nhất định, tất cả trạng thái của ngày đó sẽ được thu gom rác

11. 4. 1. Sử dụng bộ hẹn giờ để thu gom rác

Trong một số trường hợp, rất khó để tìm ra chiến lược cửa sổ mô hình hóa chiến lược thu gom rác mong muốn. Ví dụ: mong muốn chung là chuyển trạng thái thu gom rác cho một khóa sau khi không thấy hoạt động nào trên khóa trong một thời gian. Điều này có thể được thực hiện bằng cách cập nhật bộ đếm thời gian mà trạng thái thu gom rác. Ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
00

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
01

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 5. State and timers examples

Sau đây là một số ví dụ sử dụng trạng thái và bộ hẹn giờ

11. 5. 1. Kết hợp các nhấp chuột và lượt xem

Trong ví dụ này, quy trình đang xử lý dữ liệu từ trang chủ của trang thương mại điện tử. Có hai luồng đầu vào. luồng lượt xem, biểu thị các liên kết sản phẩm được đề xuất hiển thị cho người dùng trên trang chủ và luồng lượt nhấp, biểu thị lượt nhấp thực tế của người dùng vào các liên kết này. Mục tiêu của quy trình là kết hợp các sự kiện nhấp chuột với các sự kiện xem, xuất ra một sự kiện đã tham gia mới chứa thông tin từ cả hai sự kiện. Mỗi liên kết có một mã định danh duy nhất có trong cả sự kiện xem và sự kiện tham gia

Nhiều sự kiện xem sẽ không bao giờ được theo dõi bằng các nhấp chuột. Đường ống này sẽ đợi một giờ cho một nhấp chuột, sau đó nó sẽ từ bỏ tham gia này. Mặc dù mỗi sự kiện nhấp chuột phải có một sự kiện xem, nhưng một số ít sự kiện xem có thể bị mất và không bao giờ được đưa vào quy trình Beam; . Các sự kiện đầu vào không được sắp xếp - có thể thấy sự kiện nhấp chuột trước sự kiện xem. Thời gian chờ tham gia một giờ phải dựa trên thời gian sự kiện, không phải thời gian xử lý

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
03

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
04

11. 5. 2. RPC theo đợt

Trong ví dụ này, các yếu tố đầu vào đang được chuyển tiếp đến một dịch vụ RPC bên ngoài. The RPC accepts batch requests - multiple events for the same user can be batched in a single RPC call. Vì dịch vụ RPC này cũng áp đặt giới hạn tốc độ nên chúng tôi muốn gộp các sự kiện có giá trị 10 giây lại với nhau để giảm số lượng cuộc gọi

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
05

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
06

12. Có thể chia tách
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
67

Một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 có thể chia được [SDF] cho phép người dùng tạo các thành phần mô-đun có chứa I/O [và một số ] nâng cao. Việc có các thành phần I/O dạng mô-đun có thể được kết nối với nhau giúp đơn giản hóa các mẫu điển hình mà người dùng muốn. Ví dụ: trường hợp sử dụng phổ biến là đọc tên tệp từ hàng đợi tin nhắn, sau đó phân tích cú pháp các tệp đó. Theo truyền thống, người dùng được yêu cầu viết một trình kết nối I/O duy nhất chứa logic cho hàng đợi tin nhắn và trình đọc tệp [độ phức tạp tăng lên] hoặc chọn sử dụng lại I/O hàng đợi tin nhắn theo sau bởi một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 thông thường đọc tệp [ . Với SDF, chúng tôi mang đến sự phong phú của các API I/O của Apache Beam thành một mô-đun cho phép
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 trong khi vẫn duy trì hiệu suất của các đầu nối I/O truyền thống

12. 1. Khái niệm cơ bản về SDF

Ở cấp độ cao, SDF chịu trách nhiệm xử lý các cặp phần tử và giới hạn. Một hạn chế đại diện cho một tập hợp con công việc cần thiết phải được thực hiện khi xử lý phần tử

Thực hiện một SDF theo các bước sau

  1. Mỗi phần tử được ghép nối với một hạn chế [e. g. tên tệp được ghép nối với phạm vi bù đại diện cho toàn bộ tệp]
  2. Mỗi phần tử và cặp hạn chế được tách ra [e. g. offset ranges are broken up into smaller pieces]
  3. Người chạy phân phối lại các cặp phần tử và hạn chế cho một số công nhân
  4. Các cặp phần tử và giới hạn được xử lý song song [e. g. tập tin được đọc]. Trong bước cuối cùng này, cặp phần tử và giới hạn có thể tạm dừng quá trình xử lý của chính nó và/hoặc được chia thành các cặp phần tử và giới hạn khác

12. 1. 1. Một SDF cơ bản

Một SDF cơ bản bao gồm ba phần. hạn chế, nhà cung cấp hạn chế và trình theo dõi hạn chế. Nếu bạn muốn kiểm soát hình mờ, đặc biệt là trong đường ống phát trực tuyến, cần có thêm hai thành phần. nhà cung cấp công cụ ước tính thủy vân và công cụ ước tính thủy vân

Hạn chế là một đối tượng do người dùng định nghĩa được sử dụng để biểu thị một tập hợp con công việc cho một phần tử nhất định. Ví dụ: chúng tôi đã xác định

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
443 là một hạn chế để biểu thị các vị trí bù trong Java và

Trình cung cấp hạn chế cho phép các tác giả SDF ghi đè các triển khai mặc định, bao gồm cả các triển khai để phân tách và định cỡ. Trong Java và , đây là

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. có một loại
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
445 chuyên dụng

The restriction tracker is responsible for tracking which subset of the restriction has been completed during processing. For APIs details, read the Java and reference documentation

There are some built-in

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
446 implementations defined in Java

  1. OffsetRangeTracker
  2. GrowableOffsetRangeTracker
  3. ByteKeyRangeTracker

The SDF also has a built-in

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
446 implementation in Python

Go also has a built-in

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
446 type

  1. OffsetRangeTracker

The watermark state is a user-defined object which is used to create a

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
449 from a
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
450. The simplest watermark state could be a
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
451

The watermark estimator provider lets SDF authors define how to initialize the watermark state and create a watermark estimator. Trong Java và đây là

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. có loại
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
450 chuyên dụng

Công cụ ước tính thủy vân theo dõi thủy vân khi một cặp hạn chế phần tử đang được tiến hành. Để biết chi tiết về API, hãy đọc tài liệu tham khảo về Java, , và

Có một số triển khai

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
449 tích hợp sẵn trong Java

  1. Thủ công
  2. tăng đơn điệu
  3. Thời gian tường

Along with the default

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
450, there are the same set of built-in
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
449 implementations in Python

Các loại

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
449 sau đây được triển khai trong Go

Để xác định SDF, bạn phải chọn xem SDF có giới hạn [mặc định] hay không giới hạn và xác định cách khởi tạo giới hạn ban đầu cho một phần tử. Sự phân biệt dựa trên cách thể hiện khối lượng công việc

  • DoFn có giới hạn là những DoFn mà công việc được đại diện bởi một phần tử đã được biết trước và có kết thúc. Ví dụ về các phần tử được giới hạn bao gồm một tệp hoặc nhóm tệp
  • DoFns không giới hạn là những DoFn mà số lượng công việc không có điểm kết thúc cụ thể hoặc số lượng công việc không được biết trước. Ví dụ về các phần tử không giới hạn bao gồm chủ đề Kafka hoặc PubSub

Trong Java, bạn có thể sử dụng @UnboundedPerElement hoặc @BoundedPerElement để chú thích

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 của mình. Trong Python, bạn có thể sử dụng để chú thích
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
07

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
08

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
09

Tại thời điểm này, chúng tôi có một SDF hỗ trợ cho phép tái cân bằng công việc động. Để tăng tốc độ xảy ra song song hóa công việc ban đầu hoặc đối với những người chạy không hỗ trợ phân tách do người chạy bắt đầu, chúng tôi khuyên bạn nên cung cấp một tập hợp các lần phân tách ban đầu

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
10

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
11

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
12

12. 2. Sizing and progress

Định cỡ và tiến độ được sử dụng trong quá trình thực thi SDF để thông báo cho người chạy để họ có thể thực hiện các quyết định thông minh về việc phân chia hạn chế nào và cách song song hóa công việc

Trước khi xử lý một phần tử và hạn chế, người chạy có thể sử dụng kích thước ban đầu để chọn cách thức và người xử lý các hạn chế nhằm cải thiện sự cân bằng ban đầu và song song hóa công việc. Trong quá trình xử lý một phần tử và hạn chế, định cỡ và tiến độ được sử dụng để chọn phân chia hạn chế nào và ai sẽ xử lý chúng

Theo mặc định, chúng tôi sử dụng ước tính của trình theo dõi hạn chế cho công việc còn lại dựa trên giả định rằng tất cả các hạn chế đều có chi phí bằng nhau. Để ghi đè mặc định, tác giả SDF có thể cung cấp phương pháp thích hợp trong nhà cung cấp hạn chế. Các tác giả SDF cần lưu ý rằng phương pháp định cỡ sẽ được gọi đồng thời trong quá trình xử lý gói do quá trình phân tách và ước tính tiến độ bắt đầu của người chạy

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
13

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
14

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
15

12. 3. Điểm kiểm tra do người dùng khởi tạo

Một số I/O không thể tạo ra tất cả dữ liệu cần thiết để hoàn thành một hạn chế trong thời gian tồn tại của một gói. Điều này thường xảy ra với các hạn chế không giới hạn, nhưng cũng có thể xảy ra với các hạn chế có giới hạn. Ví dụ: có thể có nhiều dữ liệu cần nhập hơn nhưng chưa có sẵn. Một nguyên nhân khác của trường hợp này là do hệ thống nguồn điều chỉnh dữ liệu của bạn

SDF của bạn có thể báo hiệu cho bạn biết rằng bạn chưa xử lý xong hạn chế hiện tại. Tín hiệu này có thể gợi ý thời gian để tiếp tục tại. Trong khi người chạy cố gắng tôn trọng thời gian tiếp tục, điều này không được đảm bảo. This allows execution to continue on a restriction that has available work improving resource utilization

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
16

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
17

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
18

12. 4. Runner-khởi xướng tách

Người chạy bất cứ lúc nào cũng có thể cố gắng tách một giới hạn trong khi nó đang được xử lý. Điều này cho phép người chạy tạm dừng xử lý hạn chế để có thể thực hiện công việc khác [phổ biến đối với các hạn chế không giới hạn để hạn chế lượng đầu ra và/hoặc cải thiện độ trễ] hoặc chia hạn chế thành hai phần, tăng khả năng song song có sẵn trong hệ thống. vận động viên khác nhau [e. g. , Dataflow, Flink, Spark] có các chiến lược khác nhau để phân tách theo đợt và thực thi trực tuyến

Hãy ghi nhớ điều này khi viết một SDF vì thời điểm kết thúc hạn chế có thể thay đổi. Khi viết vòng lặp xử lý, hãy sử dụng kết quả từ việc cố gắng yêu cầu một phần của hạn chế thay vì cho rằng bạn có thể xử lý cho đến khi kết thúc

Một ví dụ không chính xác có thể là

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
19

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
20

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
21

12. 5. ước tính hình mờ

Công cụ ước tính hình mờ mặc định không tạo ra ước tính hình mờ. Therefore, the output watermark is solely computed by the minimum of upstream watermarks

Một SDF có thể nâng cao hình mờ đầu ra bằng cách chỉ định giới hạn dưới cho tất cả đầu ra trong tương lai mà phần tử này và cặp hạn chế sẽ tạo ra. Người chạy tính toán hình mờ đầu ra tối thiểu bằng cách lấy giá trị tối thiểu trên tất cả các hình mờ ngược dòng và giá trị tối thiểu được báo cáo bởi từng phần tử và cặp giới hạn. Hình mờ được báo cáo phải tăng đơn điệu cho từng phần tử và cặp hạn chế trên các ranh giới gói. Khi một phần tử và cặp hạn chế ngừng xử lý hình mờ của nó, nó không còn được coi là một phần của phép tính trên

Lời khuyên

  • Nếu bạn tạo một SDF xuất các bản ghi có dấu thời gian, bạn nên đưa ra các cách để cho phép người dùng SDF này định cấu hình công cụ ước tính hình mờ nào sẽ sử dụng
  • Bất kỳ dữ liệu nào được tạo ra trước hình mờ có thể được coi là muộn. Xem để biết thêm chi tiết

12. 5. 1. Kiểm soát hình mờ

Có hai loại công cụ ước tính thủy vân chung. quan sát dấu thời gian và quan sát đồng hồ bên ngoài. Công cụ ước tính hình mờ quan sát dấu thời gian sử dụng dấu thời gian đầu ra của mỗi bản ghi để tính toán ước tính hình mờ trong khi công cụ ước tính hình mờ quan sát đồng hồ bên ngoài kiểm soát hình mờ bằng cách sử dụng đồng hồ không được liên kết với bất kỳ đầu ra riêng lẻ nào, chẳng hạn như đồng hồ cục bộ của máy hoặc đồng hồ tiếp xúc

Nhà cung cấp công cụ ước tính hình mờ cho phép bạn ghi đè logic ước tính hình mờ mặc định và sử dụng triển khai công cụ ước tính hình mờ hiện có. Bạn cũng có thể cung cấp triển khai ước tính hình mờ của riêng mình

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
22

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
23

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
24

12. 6. Cắt ngắn trong quá trình thoát nước

Người chạy hỗ trợ đường ống thoát nước cần có khả năng thoát SDF; . Theo mặc định, các hạn chế có giới hạn xử lý phần còn lại của hạn chế trong khi các hạn chế không có giới hạn kết thúc quá trình xử lý tại điểm kiểm tra do SDF bắt đầu tiếp theo hoặc phân tách do người chạy bắt đầu. Bạn có thể ghi đè hành vi mặc định này bằng cách xác định phương thức thích hợp trên trình cung cấp hạn chế

Ghi chú. Sau khi quá trình thoát đường ống bắt đầu và biến đổi hạn chế cắt ngắn được kích hoạt,

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
460 sẽ không được lên lịch lại

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
25

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
26

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
27

12. 7. Quyết toán gói

Hoàn thiện gói cho phép một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 thực hiện các tác dụng phụ bằng cách đăng ký gọi lại. Cuộc gọi lại được gọi sau khi người chạy đã thừa nhận rằng nó đã duy trì đầu ra một cách lâu dài. Ví dụ: một hàng đợi tin nhắn có thể cần xác nhận các tin nhắn mà nó đã nhập vào đường dẫn. Bundle finalization is not limited to SDFs but is called out here since this is the primary use case

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
28

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
29

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
30

13. Đường ống đa ngôn ngữ

Phần này cung cấp tài liệu toàn diện về các đường dẫn đa ngôn ngữ. Để bắt đầu tạo một kênh dẫn đa ngôn ngữ, hãy xem

  • Khởi động nhanh đường dẫn đa ngôn ngữ Python
  • Khởi động nhanh đường dẫn đa ngôn ngữ Java

Beam cho phép bạn kết hợp các biến đổi được viết bằng bất kỳ ngôn ngữ SDK được hỗ trợ nào [hiện tại là Java và Python] và sử dụng chúng trong một kênh dẫn đa ngôn ngữ. Khả năng này giúp dễ dàng cung cấp chức năng mới đồng thời trong các Apache Beam SDK khác nhau thông qua một chuyển đổi ngôn ngữ chéo duy nhất. Ví dụ: trình kết nối Apache Kafka và chuyển đổi SQL từ SDK Java có thể được sử dụng trong các đường dẫn Python

Các quy trình sử dụng biến đổi từ nhiều ngôn ngữ SDK được gọi là quy trình đa ngôn ngữ

13. 1. Tạo chuyển đổi ngôn ngữ chéo

Để cung cấp các biến đổi được viết bằng một ngôn ngữ cho các quy trình được viết bằng ngôn ngữ khác, Beam sử dụng một dịch vụ mở rộng, dịch vụ này tạo và đưa các đoạn quy trình dành riêng cho ngôn ngữ thích hợp vào quy trình

Trong ví dụ sau, một đường dẫn Beam Python khởi động một dịch vụ mở rộng Java cục bộ để tạo và thêm các đoạn đường dẫn Java thích hợp để thực thi chuyển đổi ngôn ngữ chéo Java Kafka thành đường dẫn Python. The SDK then downloads and stages the necessary Java dependencies needed to execute these transforms

Khi chạy, trình chạy Beam sẽ thực thi cả hai phép biến đổi Python và Java để chạy đường dẫn

Trong phần này, chúng tôi sẽ sử dụng KafkaIO. Đọc để minh họa cách tạo chuyển đổi ngôn ngữ chéo cho Java và ví dụ thử nghiệm cho Python

13. 1. 1. Tạo các biến đổi Java đa ngôn ngữ

Có hai cách để cung cấp các biến đổi Java cho các SDK khác

  • lựa chọn 1. Trong một số trường hợp, bạn có thể sử dụng các biến đổi Java hiện có từ các SDK khác mà không cần viết thêm bất kỳ mã Java nào
  • Lựa chọn 2. Bạn có thể sử dụng các biến đổi Java tùy ý từ các SDK khác bằng cách thêm một vài lớp Java
13. 1. 1. 1 Sử dụng các biến đổi Java hiện có mà không cần viết thêm mã Java

Bắt đầu với Beam 2. 34. 0, người dùng SDK Python có thể sử dụng một số biến đổi Java mà không cần viết mã Java bổ sung. Điều này có thể hữu ích trong nhiều trường hợp. Ví dụ

  • Nhà phát triển không quen thuộc với Java có thể cần sử dụng biến đổi Java hiện có từ đường dẫn Python
  • A developer may need to make an existing Java transform available to a Python pipeline without writing/releasing more Java code

Ghi chú. Tính năng này hiện chỉ khả dụng khi sử dụng các biến đổi Java từ một đường dẫn Python

Để đủ điều kiện sử dụng trực tiếp, API của biến đổi Java phải đáp ứng các yêu cầu sau

  1. Biến đổi Java có thể được xây dựng bằng cách sử dụng hàm tạo công khai có sẵn hoặc phương thức tĩnh công khai [phương thức tạo] trong cùng một lớp Java
  2. Biến đổi Java có thể được cấu hình bằng một hoặc nhiều phương thức trình tạo. Mỗi phương thức của trình tạo phải ở chế độ công khai và sẽ trả về một phiên bản của biến đổi Java

Đây là một lớp Java mẫu có thể được sử dụng trực tiếp từ API Python

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
31

Để biết ví dụ hoàn chỉnh, hãy xem JavaDataGenerator

Để sử dụng một lớp Java tuân thủ các yêu cầu trên từ đường dẫn SDK Python, hãy làm theo các bước sau

  1. Tạo danh sách cho phép yaml mô tả các lớp và phương thức biến đổi Java sẽ được truy cập trực tiếp từ Python
  2. Bắt đầu một dịch vụ mở rộng, sử dụng tùy chọn
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    462 để chuyển đường dẫn đến danh sách cho phép
  3. Sử dụng API JavaExternalTransform của Python để truy cập trực tiếp các biến đổi Java được xác định trong danh sách cho phép từ phía Python

Bắt đầu với Beam 2. 36. 0, có thể bỏ qua bước 1 và 2, như được mô tả trong các phần tương ứng bên dưới

Bước 1

Để sử dụng biến đổi Java đủ điều kiện từ Python, hãy xác định danh sách cho phép yaml. This allowlist lists the class names, constructor methods, and builder methods that are directly available to be used from the Python side

Bắt đầu với Beam 2. 35. 0, bạn có tùy chọn chuyển

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
009 sang tùy chọn
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
462 thay vì xác định danh sách cho phép thực tế.
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
009 chỉ định rằng tất cả các biến đổi được hỗ trợ trong đường dẫn lớp của dịch vụ mở rộng có thể được truy cập thông qua API. Chúng tôi khuyến khích sử dụng danh sách cho phép thực tế để sản xuất, vì việc cho phép khách hàng truy cập các lớp Java tùy ý có thể gây ra rủi ro bảo mật

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
32

Bước 2

Cung cấp danh sách cho phép làm đối số khi khởi động dịch vụ mở rộng Java. Ví dụ: bạn có thể bắt đầu dịch vụ mở rộng dưới dạng quy trình Java cục bộ bằng cách sử dụng lệnh sau

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
33

Bắt đầu với Beam 2. 36. 0, API

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
466 sẽ tự động khởi động dịch vụ mở rộng với phần phụ thuộc tệp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
467 nhất định nếu địa chỉ dịch vụ mở rộng không được cung cấp

Bước 3

Bạn có thể sử dụng lớp Java trực tiếp từ đường dẫn Python của mình bằng cách sử dụng một biến đổi sơ khai được tạo từ API

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
466. API này cho phép bạn xây dựng biến đổi bằng cách sử dụng tên lớp Java và cho phép bạn gọi các phương thức của trình tạo để định cấu hình lớp

Các loại tham số của hàm tạo và phương thức được ánh xạ giữa Python và Java bằng cách sử dụng lược đồ Beam. The schema is auto-generated using the object types provided on the Python side. Nếu phương thức hàm tạo lớp Java hoặc phương thức trình tạo chấp nhận bất kỳ loại đối tượng phức tạp nào, hãy đảm bảo rằng lược đồ Beam cho các đối tượng này đã được đăng ký và sẵn dùng cho dịch vụ mở rộng Java. Nếu lược đồ chưa được đăng ký, dịch vụ mở rộng Java sẽ cố gắng đăng ký lược đồ bằng cách sử dụng. Trong Python, các đối tượng tùy ý có thể được biểu diễn bằng cách sử dụng các

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
055, sẽ được biểu diễn dưới dạng các hàng Beam trong lược đồ. Đây là một biến đổi sơ khai Python đại diện cho biến đổi Java đã đề cập ở trên

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
34

Bạn có thể sử dụng biến đổi này trong một đường dẫn Python cùng với các biến đổi Python khác. Để biết ví dụ hoàn chỉnh, hãy xem javadatagenerator. py

13. 1. 1. 2 Sử dụng API để cung cấp các biến đổi Java hiện có cho các SDK khác

Để làm cho Beam Java SDK của bạn có thể chuyển đổi linh hoạt trên các ngôn ngữ SDK, bạn phải triển khai hai giao diện. ExternalTransformBuilder and ExternalTransformRegistrar. Giao diện

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
470 xây dựng chuyển đổi ngôn ngữ chéo bằng cách sử dụng các giá trị cấu hình được truyền vào từ đường ống và giao diện
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
471 đăng ký chuyển đổi ngôn ngữ chéo để sử dụng với dịch vụ mở rộng

Triển khai các giao diện

  1. Xác định lớp Trình tạo cho phép biến đổi của bạn để triển khai giao diện

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    470 và ghi đè phương thức
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    473 sẽ được sử dụng để xây dựng đối tượng biến đổi của bạn. Các giá trị cấu hình ban đầu cho biến đổi của bạn phải được xác định theo phương thức
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    473. Trong hầu hết các trường hợp, thật tiện lợi khi làm cho lớp trình tạo biến đổi Java triển khai
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    470

    Ghi chú.

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    470 requires you to define a configuration object [a simple POJO] to capture a set of parameters sent by external SDKs to initiate the Java transform. Thông thường, các tham số này ánh xạ trực tiếp tới các tham số hàm tạo của biến đổi Java

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    35

    Để biết các ví dụ đầy đủ, hãy xem JavaCountBuilder và JavaPrefixBuilder

    Lưu ý rằng phương pháp

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    473 có thể thực hiện các thao tác bổ sung trước khi đặt các thuộc tính nhận được từ SDK bên ngoài trong quá trình chuyển đổi. Ví dụ:
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    473 có thể xác thực các thuộc tính có sẵn trong đối tượng cấu hình trước khi đặt chúng trong biến đổi

  2. Đăng ký biến đổi dưới dạng biến đổi ngôn ngữ chéo bên ngoài bằng cách xác định một lớp thực hiện

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    471. Bạn phải chú thích lớp của mình bằng chú thích
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    480 để đảm bảo rằng biến đổi của bạn được đăng ký và khởi tạo đúng cách bởi dịch vụ mở rộng

  3. Trong lớp công ty đăng ký của bạn, hãy xác định Tên tài nguyên thống nhất [URN] cho biến đổi của bạn. The URN must be a unique string that identifies your transform with the expansion service

  4. Từ bên trong lớp công ty đăng ký của bạn, hãy xác định lớp cấu hình cho các tham số được sử dụng trong quá trình khởi tạo chuyển đổi của bạn bằng SDK bên ngoài

    Ví dụ sau đây từ phép biến đổi KafkaIO cho thấy cách thực hiện các bước từ hai đến bốn

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    36

    Để biết thêm ví dụ, hãy xem JavaCountRegistrar và JavaPrefixRegistrar

Sau khi bạn đã triển khai các giao diện

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
470 và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
471, biến đổi của bạn có thể được đăng ký và tạo thành công bởi dịch vụ mở rộng Java mặc định

Bắt đầu dịch vụ mở rộng

Bạn có thể sử dụng dịch vụ mở rộng với nhiều biến đổi trong cùng một quy trình. Beam Java SDK cung cấp dịch vụ mở rộng mặc định cho các biến đổi Java. Bạn cũng có thể viết dịch vụ mở rộng của riêng mình, nhưng điều đó thường không cần thiết, vì vậy nó không được đề cập trong phần này

Perform the following to start up a Java expansion service directly

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
37

Dịch vụ mở rộng hiện đã sẵn sàng để phục vụ các biến đổi trên cổng được chỉ định

Khi tạo trình bao bọc dành riêng cho SDK cho biến đổi của mình, bạn có thể sử dụng các tiện ích do SDK cung cấp để bắt đầu dịch vụ mở rộng. Ví dụ: SDK Python cung cấp các tiện ích và để khởi động dịch vụ mở rộng Java bằng tệp JAR

bao gồm các phụ thuộc

Nếu biến đổi của bạn yêu cầu các thư viện bên ngoài, bạn có thể đưa chúng vào bằng cách thêm chúng vào đường dẫn lớp của dịch vụ mở rộng. Sau khi chúng được đưa vào đường dẫn lớp, chúng sẽ được phân đoạn khi biến đổi của bạn được mở rộng bởi dịch vụ mở rộng

Viết trình bao bọc dành riêng cho SDK

Chuyển đổi Java ngôn ngữ chéo của bạn có thể được gọi thông qua lớp cấp thấp hơn trong một đường dẫn đa ngôn ngữ [như được mô tả trong phần tiếp theo]; . Sự trừu tượng hóa cấp cao hơn này sẽ giúp các tác giả đường ống sử dụng biến đổi của bạn dễ dàng hơn

Để tạo trình bao bọc SDK để sử dụng trong đường dẫn Python, hãy làm như sau

  1. Tạo một mô-đun Python cho [các] biến đổi ngôn ngữ chéo của bạn

  2. Trong mô-đun, sử dụng một trong các lớp để xây dựng tải trọng cho yêu cầu mở rộng chuyển đổi ngôn ngữ chéo ban đầu

    Tên tham số và loại tải trọng phải ánh xạ tới tên tham số và loại cấu hình POJO được cung cấp cho Java

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    470. Các loại tham số được ánh xạ trên các SDK bằng lược đồ Beam. Tên tham số được ánh xạ bằng cách đơn giản chuyển đổi tên biến được phân tách bằng dấu gạch dưới Python thành trường hợp lạc đà [tiêu chuẩn Java]

    Trong ví dụ sau, kafka. py uses

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    488 to build the payload. Các tham số ánh xạ tới Java KafkaIO. Bên ngoài. Đối tượng cấu hình cấu hình được xác định trong phần trước

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    38

  3. Bắt đầu một dịch vụ mở rộng, trừ khi một dịch vụ được chỉ định bởi người tạo đường ống. Beam Python SDK cung cấp các tiện ích và để khởi động dịch vụ mở rộng bằng tệp JAR. có thể được sử dụng để khởi động dịch vụ mở rộng bằng cách sử dụng đường dẫn [đường dẫn cục bộ hoặc URL] tới tệp JAR đã cho. có thể được sử dụng để bắt đầu dịch vụ mở rộng từ JAR được phát hành với Beam

    Đối với các biến đổi được phát hành bằng Beam, hãy làm như sau

    1. Thêm mục tiêu Gradle vào Beam có thể được sử dụng để xây dựng JAR dịch vụ mở rộng bóng mờ cho biến đổi Java mục tiêu. Mục tiêu này sẽ tạo ra một Beam JAR chứa tất cả các phụ thuộc cần thiết để mở rộng biến đổi Java và JAR sẽ được phát hành cùng với Beam. Bạn có thể sử dụng mục tiêu Gradle hiện có cung cấp phiên bản tổng hợp của dịch vụ mở rộng JAR [ví dụ: cho tất cả GCP IO]

    2. Trong mô-đun Python của bạn, khởi tạo

      import apache_beam as beam
      
      with beam.Pipeline[] as pipeline:
        pass  # build your pipeline here
      484 với mục tiêu Gradle

      await beam.createRunner[].run[function pipeline[root] {
        // Use root to build a pipeline.
      }];
      
      39

  4. Thêm một lớp biến đổi trình bao bọc Python mở rộng. Truyền tải trọng và dịch vụ mở rộng được định nghĩa ở trên dưới dạng tham số cho hàm tạo của lớp cha

13. 1. 2. Tạo các biến đổi Python đa ngôn ngữ

Any Python transforms defined in the scope of the expansion service should be accessible by specifying their fully qualified names. Ví dụ: bạn có thể sử dụng biến đổi

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
496 của Python trong một đường ống dẫn Java với tên đủ điều kiện của nó là
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
497

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
40

Ghi chú.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
498 có các phương pháp hữu ích khác, chẳng hạn như
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
499 để dàn dựng các phụ thuộc gói PyPI và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
500 để đặt bộ mã hóa đầu ra

Ngoài ra, bạn có thể muốn tạo một mô-đun Python đăng ký một biến đổi Python hiện có dưới dạng một biến đổi ngôn ngữ chéo để sử dụng với dịch vụ mở rộng Python và gọi vào biến đổi hiện có đó để thực hiện thao tác dự định của nó. Một URN đã đăng ký có thể được sử dụng sau này trong yêu cầu mở rộng để chỉ ra mục tiêu mở rộng

Xác định mô-đun Python

  1. Xác định Tên tài nguyên thống nhất [URN] cho biến đổi của bạn. URN phải là một chuỗi duy nhất xác định biến đổi của bạn với dịch vụ mở rộng

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    41

  2. Đối với một biến đổi Python hiện có, hãy tạo một lớp mới để đăng ký URN với dịch vụ mở rộng Python

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    42

  3. Từ bên trong lớp, xác định phương thức mở rộng lấy PCollection đầu vào, chạy biến đổi Python, sau đó trả về PCollection đầu ra

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    43

  4. As with other Python transforms, define a

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    501 method that returns the URN

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    44

  5. Xác định một phương thức tĩnh

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    502 trả về một khởi tạo của biến đổi Python đa ngôn ngữ

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    45

Bắt đầu dịch vụ mở rộng

Một dịch vụ mở rộng có thể được sử dụng với nhiều biến đổi trong cùng một đường ống. Beam Python SDK cung cấp dịch vụ mở rộng mặc định để bạn sử dụng với các biến đổi Python của mình. Bạn có thể tự do viết dịch vụ mở rộng của riêng mình, nhưng điều đó thường không cần thiết, vì vậy nó không được đề cập trong phần này

Thực hiện các bước sau để khởi động trực tiếp dịch vụ mở rộng Python mặc định

  1. Tạo một môi trường ảo và cài đặt Apache Beam SDK

  2. Bắt đầu dịch vụ mở rộng của SDK Python với một cổng được chỉ định

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    46

  3. Nhập bất kỳ mô-đun nào có chứa các biến đổi sẽ được cung cấp bằng dịch vụ mở rộng

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    47

  4. Dịch vụ mở rộng này hiện đã sẵn sàng để phục vụ các biến đổi trên địa chỉ

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    503

bao gồm các phụ thuộc

Hiện tại, các phép biến đổi bên ngoài của Python bị giới hạn ở các phần phụ thuộc có sẵn trong bộ khai thác Beam SDK cốt lõi

13. 1. 3. Tạo biến đổi ngôn ngữ chéo

Go hiện không hỗ trợ tạo biến đổi ngôn ngữ chéo, chỉ sử dụng biến đổi ngôn ngữ chéo từ các ngôn ngữ khác;

13. 1. 4. Defining a URN

Phát triển chuyển đổi ngôn ngữ chéo liên quan đến việc xác định URN để đăng ký chuyển đổi với dịch vụ mở rộng. Trong phần này, chúng tôi cung cấp một quy ước để xác định các URN như vậy. Việc tuân theo quy ước này là tùy chọn nhưng nó sẽ đảm bảo rằng biến đổi của bạn sẽ không gặp xung đột khi đăng ký dịch vụ mở rộng cùng với các biến đổi do các nhà phát triển khác phát triển

13. 1. 4. 1. Lược đồ

Một URN nên bao gồm các thành phần sau

  • ns-id. Một định danh không gian tên. Khuyến nghị mặc định là
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    504
  • định danh tổ chức. Xác định tổ chức nơi chuyển đổi được xác định. Các biến đổi được xác định trong Apache Beam sử dụng
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    505 cho việc này
  • định danh chức năng. Xác định chức năng của chuyển đổi ngôn ngữ chéo
  • phiên bản. một số phiên bản cho chuyển đổi

Chúng tôi cung cấp lược đồ từ quy ước URN ở dạng Backus–Naur tăng cường. Từ khóa trong chữ hoa là từ thông số URN

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
48

13. 1. 4. 2. ví dụ

Dưới đây chúng tôi đã đưa ra một số ví dụ về các lớp biến đổi và các URN tương ứng sẽ được sử dụng

  • Một biến đổi được cung cấp với Apache Beam để ghi các tệp Parquet
    • import apache_beam as beam
      
      with beam.Pipeline[] as pipeline:
        pass  # build your pipeline here
      506
  • Một biến đổi được cung cấp với Apache Beam đọc từ Kafka với siêu dữ liệu
    • import apache_beam as beam
      
      with beam.Pipeline[] as pipeline:
        pass  # build your pipeline here
      507
  • Một chuyển đổi được phát triển bởi tổ chức abc. org đọc từ kho dữ liệu MyDatastore
    • import apache_beam as beam
      
      with beam.Pipeline[] as pipeline:
        pass  # build your pipeline here
      508

13. 2. Sử dụng biến đổi ngôn ngữ chéo

Depending on the SDK language of the pipeline, you can use a high-level SDK-wrapper class, or a low-level transform class to access a cross-language transform

13. 2. 1. Sử dụng các biến đổi ngôn ngữ chéo trong một đường dẫn Java

Người dùng có ba tùy chọn để sử dụng chuyển đổi ngôn ngữ chéo trong đường dẫn Java. Ở mức độ trừu tượng cao nhất, một số biến đổi Python phổ biến có thể truy cập được thông qua các biến đổi trình bao bọc Java chuyên dụng. Ví dụ: SDK Java có lớp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
509, lớp này sử dụng lớp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
509 của SDK Python và lớp này có lớp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
511, lớp này sử dụng lớp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
511 của SDK Python, v.v. Khi biến đổi trình bao bọc dành riêng cho SDK không có sẵn cho biến đổi Python đích, bạn có thể sử dụng lớp PythonExternalTransform cấp thấp hơn thay vào đó bằng cách chỉ định tên đủ điều kiện của biến đổi Python. Nếu bạn muốn thử chuyển đổi bên ngoài từ SDK khác ngoài Python [bao gồm cả SDK Java], bạn cũng có thể sử dụng lớp Bên ngoài cấp thấp nhất

Sử dụng trình bao bọc SDK

Để sử dụng chuyển đổi ngôn ngữ chéo thông qua trình bao bọc SDK, hãy nhập mô-đun cho trình bao bọc SDK và gọi nó từ quy trình của bạn, như minh họa trong ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
49

Sử dụng lớp PythonExternalTransform

Khi không có trình bao bọc dành riêng cho SDK, bạn có thể truy cập biến đổi đa ngôn ngữ Python thông qua lớp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
498 bằng cách chỉ định tên đủ điều kiện và đối số hàm tạo của biến đổi Python đích

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
50

Sử dụng lớp bên ngoài

  1. Đảm bảo rằng bạn đã cài đặt mọi phụ thuộc môi trường thời gian chạy [như JRE] trên máy cục bộ của mình [trực tiếp trên máy cục bộ hoặc có sẵn thông qua bộ chứa]. Xem phần dịch vụ mở rộng để biết thêm chi tiết

    Ghi chú. Khi bao gồm các biến đổi Python từ bên trong đường dẫn Java, tất cả các phần phụ thuộc Python phải được bao gồm trong bộ chứa khai thác SDK

  2. Bắt đầu dịch vụ mở rộng cho SDK bằng ngôn ngữ của biến đổi mà bạn đang cố gắng sử dụng, nếu không có sẵn

    Make sure the transform you are trying to use is available and can be used by the expansion service

  3. Bao gồm bên ngoài. of[…] khi khởi tạo đường dẫn của bạn. Tham khảo dịch vụ URN, tải trọng và mở rộng. Ví dụ, xem bộ thử nghiệm chuyển đổi ngôn ngữ chéo

  4. Sau khi công việc đã được gửi tới trình chạy Beam, hãy tắt dịch vụ mở rộng bằng cách chấm dứt quy trình dịch vụ mở rộng

13. 2. 2. Sử dụng các biến đổi ngôn ngữ chéo trong một đường dẫn Python

Nếu có trình bao bọc dành riêng cho Python cho biến đổi ngôn ngữ chéo, hãy sử dụng trình bao bọc đó. Mặt khác, bạn phải sử dụng lớp cấp thấp hơn để truy cập biến đổi

Sử dụng trình bao bọc SDK

Để sử dụng chuyển đổi ngôn ngữ chéo thông qua trình bao bọc SDK, hãy nhập mô-đun cho trình bao bọc SDK và gọi nó từ quy trình của bạn, như minh họa trong ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
51

Sử dụng lớp ExternalTransform

Khi không có trình bao bọc dành riêng cho SDK, bạn sẽ phải truy cập vào biến đổi ngôn ngữ chéo thông qua lớp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
485

  1. Đảm bảo rằng bạn đã cài đặt mọi phụ thuộc môi trường thời gian chạy [như JRE] trên máy cục bộ của mình. Xem phần dịch vụ mở rộng để biết thêm chi tiết

  2. Bắt đầu dịch vụ mở rộng cho SDK bằng ngôn ngữ của biến đổi mà bạn đang cố gắng sử dụng, nếu không có sẵn. Python cung cấp một số lớp để tự động bắt đầu các dịch vụ java mở rộng, chẳng hạn như và có thể được chuyển trực tiếp dưới dạng dịch vụ mở rộng tới

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    516. Đảm bảo rằng biến đổi bạn đang cố sử dụng có sẵn và có thể được sử dụng bởi dịch vụ mở rộng

    Đối với Java, đảm bảo rằng trình xây dựng và công ty đăng ký cho biến đổi có sẵn trong đường dẫn lớp của dịch vụ mở rộng

  3. Include

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    485 when instantiating your pipeline. Tham khảo dịch vụ URN, tải trọng và mở rộng. Bạn có thể sử dụng một trong các lớp có sẵn để xây dựng tải trọng cho
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    485

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    52

    Để biết thêm ví dụ, hãy xem addprefix. py và javacount. py

  4. Sau khi công việc đã được gửi tới trình chạy Beam, hãy tắt mọi dịch vụ mở rộng được bắt đầu thủ công bằng cách chấm dứt quy trình dịch vụ mở rộng

Sử dụng lớp JavaExternalTransform

Python có khả năng gọi các phép biến đổi do Java định nghĩa thông qua như thể chúng là các phép biến đổi Python. Chúng được gọi như sau

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
53

Phương thức

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
520 của Python có thể được sử dụng nếu tên phương thức trong java là các từ khóa Python dành riêng, chẳng hạn như
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
521

Cũng như các biến đổi bên ngoài khác, có thể cung cấp dịch vụ mở rộng bắt đầu trước hoặc các tệp jar bao gồm biến đổi, các phần phụ thuộc của nó và dịch vụ mở rộng của Beam, trong trường hợp đó, dịch vụ mở rộng sẽ tự động khởi động

13. 2. 3. Sử dụng chuyển đổi ngôn ngữ chéo trong đường dẫn Go

Nếu có sẵn trình bao bọc dành riêng cho ngôn ngữ chéo, hãy sử dụng trình bao bọc đó. Mặt khác, bạn phải sử dụng chức năng cấp thấp hơn để truy cập biến đổi

Dịch vụ mở rộng

Go SDK hỗ trợ tự động bắt đầu các dịch vụ mở rộng Java nếu địa chỉ mở rộng không được cung cấp, mặc dù điều này chậm hơn so với việc cung cấp dịch vụ mở rộng liên tục. Nhiều biến đổi Java được bao gói quản lý thực hiện việc này một cách tự động; . Để sử dụng chuyển đổi ngôn ngữ chéo Python, bạn phải bắt đầu thủ công bất kỳ dịch vụ mở rộng cần thiết nào trên máy cục bộ của mình và đảm bảo chúng có thể truy cập được vào mã của bạn trong quá trình xây dựng đường ống

Sử dụng trình bao bọc SDK

Để sử dụng chuyển đổi ngôn ngữ chéo thông qua trình bao bọc SDK, hãy nhập gói cho trình bao bọc SDK và gọi gói đó từ quy trình của bạn như minh họa trong ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
54

Sử dụng chức năng CrossLanguage

Khi không có trình bao bọc dành riêng cho SDK, bạn sẽ phải truy cập vào chuyển đổi ngôn ngữ chéo thông qua chức năng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
523

  1. Đảm bảo bạn có dịch vụ mở rộng phù hợp đang chạy. Xem phần dịch vụ mở rộng để biết chi tiết

  2. Đảm bảo rằng biến đổi bạn đang cố sử dụng có sẵn và có thể được sử dụng bởi dịch vụ mở rộng. Tham khảo để biết chi tiết

  3. Sử dụng chức năng

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    523 trong quy trình bán hàng của bạn khi thích hợp. Tham khảo URN, tải trọng, địa chỉ dịch vụ mở rộng và xác định đầu vào và đầu ra. Bạn có thể sử dụng chức năng này như một công cụ trợ giúp để mã hóa tải trọng. Bạn có thể sử dụng các hàm và làm lối tắt cho các đầu vào/đầu ra đơn lẻ, không tên hoặc xác định bản đồ cho các đầu vào/đầu ra được đặt tên

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    55

  4. Sau khi công việc đã được gửi tới trình chạy Beam, hãy tắt dịch vụ mở rộng bằng cách chấm dứt quy trình dịch vụ mở rộng

13. 2. 4. Sử dụng các biến đổi ngôn ngữ chéo trong một đường ống Bản mô tả

Using a Typescript wrapper for a cross-language pipeline is similar to using any other transform, provided the dependencies [e. g. một trình thông dịch Python gần đây hoặc Java JRE] có sẵn. Ví dụ: hầu hết các IO Bản mô tả chỉ đơn giản là các trình bao bọc xung quanh các biến đổi Beam từ các ngôn ngữ khác

Nếu trình bao bọc chưa có sẵn, người ta có thể sử dụng nó một cách rõ ràng bằng cách sử dụng apache_beam. biến đổi. bên ngoài. rawExternalTransform. lấy `urn` [chuỗi xác định biến đổi], `payload` [đối tượng nhị phân hoặc json tham số hóa biến đổi] và `expansionService` có thể là địa chỉ của dịch vụ bắt đầu trước hoặc trả về có thể gọi được

Ví dụ, người ta có thể viết

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
56

Lưu ý rằng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
525 phải có bộ mã hóa tương thích đa ngôn ngữ, chẳng hạn như
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
526. Điều này có thể được đảm bảo với các biến đổi withCoderInternal hoặc withRowCoder, e. g

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
57

Coder cũng có thể được chỉ định trên đầu ra nếu nó không thể được suy ra, e. g

Ngoài ra, có một số tiện ích như pythonTransform giúp gọi các phép biến đổi từ các ngôn ngữ cụ thể dễ dàng hơn

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
58

Chuyển đổi ngôn ngữ chéo cũng có thể được xác định theo dòng, có thể hữu ích để truy cập các tính năng hoặc thư viện không có sẵn trong SDK gọi

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
59

13. 3. Hỗ trợ người chạy

Hiện tại, các trình chạy di động như Flink, Spark và trình chạy trực tiếp có thể được sử dụng với các đường dẫn đa ngôn ngữ

Dataflow hỗ trợ các đường ống đa ngôn ngữ thông qua kiến ​​trúc phụ trợ Dataflow Runner v2

13. 4 mẹo và khắc phục sự cố

Để biết thêm mẹo và thông tin khắc phục sự cố, hãy xem tại đây

14 DoFn theo đợt

Thích ứng cho
  • SDK Java
  • SDK Python
  • Truy cập SDK
  • SDK TypeScript

Batched DoFns hiện là một tính năng chỉ dành cho Python

Batched DoFns cho phép người dùng tạo các thành phần mô-đun, có thể kết hợp hoạt động theo lô gồm nhiều thành phần logic. Các DoFn này có thể tận dụng các thư viện Python được vector hóa, như numpy, scipy và pandas, hoạt động trên các lô dữ liệu để đạt hiệu quả

14. 1 Khái niệm cơ bản

Batched DoFns hiện là một tính năng chỉ dành cho Python

Một Batched DoFn tầm thường có thể trông như thế này

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
60

DoFn này có thể được sử dụng trong đường ống Beam hoạt động trên các phần tử riêng lẻ. Beam sẽ hoàn toàn đệm các phần tử và tạo các mảng có nhiều mảng ở phía đầu vào và ở phía đầu ra, nó sẽ phân tách các mảng có nhiều mảng thành các phần tử riêng lẻ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
61

Note that we use to set the element-wise typehint for the output of

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
528. Then, when
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
529 is applied to this
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, Beam recognizes that
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
531 is an acceptable batch type to use in conjunction with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
532 elements. Chúng tôi sẽ sử dụng các gợi ý kiểu chữ gọn gàng như thế này trong suốt hướng dẫn này, nhưng Beam cũng hỗ trợ các gợi ý kiểu chữ từ các thư viện khác, hãy xem

Trong trường hợp trước, Beam sẽ ngầm tạo và phát nổ các lô ở ranh giới đầu vào và đầu ra. Tuy nhiên, nếu Batched DoFns với các loại tương đương được xâu chuỗi lại với nhau, việc tạo và phát nổ hàng loạt này sẽ bị loại bỏ. Các lô sẽ được chuyển thẳng qua. Điều này làm cho việc tổng hợp hiệu quả các biến đổi hoạt động theo lô trở nên đơn giản hơn nhiều

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
62

14. Dự phòng 2 phần tử

Batched DoFns hiện là một tính năng chỉ dành cho Python

Đối với một số DoFns, bạn có thể cung cấp cả triển khai theo đợt và theo từng phần tử theo logic mong muốn của mình. Bạn có thể làm điều này bằng cách chỉ cần xác định cả

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
534

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
63

Khi thực hiện DoFn này, Beam sẽ chọn cách triển khai tốt nhất để sử dụng trong bối cảnh nhất định. Nói chung, nếu các đầu vào cho DoFn đã được theo đợt thì Beam sẽ sử dụng triển khai theo đợt;

Lưu ý rằng, trong trường hợp này, không cần xác định

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
536. Điều này là do Beam có thể lấy loại đầu ra từ gợi ý đánh máy trên
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30

14. 3 Sản xuất hàng loạt so với. tiêu thụ hàng loạt

Batched DoFns hiện là một tính năng chỉ dành cho Python

Theo quy ước, Beam giả định rằng phương pháp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
534, sử dụng các đầu vào theo đợt, cũng sẽ tạo ra các đầu ra theo đợt. Similarly, Beam assumes the
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method will produce individual elements. Điều này có thể được ghi đè bằng và trang trí. Ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
64

14. 4 loại lô được hỗ trợ

Batched DoFns hiện là một tính năng chỉ dành cho Python

Chúng tôi đã sử dụng các loại numpy trong triển khai Batched DoFn trong hướng dẫn này –

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
542 làm gợi ý kiểu phần tử và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
531 làm gợi ý kiểu lô tương ứng – nhưng Beam cũng hỗ trợ các gợi ý kiểu chữ từ các thư viện khác

cục mịch

Loại phần tửgợi ýLoại hàng loạtgợi ýCác loại số [
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
545,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
546,…] np. ndarray [của Mảng Numpy]

gấu trúc

Loại phần tửgợi ýLoại hàng loạtgợi ýCác loại số [
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
545,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
546,…]
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
550
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
551
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
060
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
553

cây kim tước

Element TypehintBatch TypehintNumeric types [
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
545,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
546, …]
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
550
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
060
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
83
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
560
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
561

Các loại khác?

Nếu có các loại lô khác mà bạn muốn sử dụng với Batched DoFns, vui lòng gửi vấn đề

14. 5 loại đầu vào và đầu ra hàng loạt động

Batched DoFns hiện là một tính năng chỉ dành cho Python

Đối với một số DoFns theo lô, có thể không đủ để khai báo các loại lô một cách tĩnh, với gợi ý đánh máy trên

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 và/hoặc
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
534. Bạn có thể cần phải khai báo động các kiểu này. Bạn có thể thực hiện việc này bằng cách ghi đè các phương thức và trên DoFn của mình

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
65

14. 6 lô và ngữ nghĩa thời gian sự kiện

Batched DoFns hiện là một tính năng chỉ dành cho Python

Hiện tại, các lô phải có một bộ thông tin thời gian duy nhất [thời gian sự kiện, cửa sổ, v.v.] áp dụng cho mọi thành phần logic trong lô. Hiện tại không có cơ chế để tạo các lô kéo dài nhiều dấu thời gian. Tuy nhiên, có thể truy xuất thông tin thời gian này trong triển khai Batched DoFn. Thông tin này có thể được truy cập bằng cách sử dụng các thuộc tính

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
566 thông thường

Chủ Đề