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
68. Mộtawait 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ộtawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
68. Khi bạn tạoawait 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ủaawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
68await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
73. Aawait 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 initialawait 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 aawait 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 pipelineawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
78. Aawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
78 represents a data processing operation, or a step, in your pipeline. Everyawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
78 takes one or moreawait 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 thatawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
73, and produces zero or more outputawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
73 objectsawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
84. The Go SDK has an explicit scope variable used to build aawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
68. Aawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
68 can return it’s root scope with theawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
87 method. The scope variable is passed toawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
78 functions to place them in theawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
68 that owns theawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
84await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- I/O transforms. Beam comes with a number of “IOs” - library
78s that read or write data to various external storage systemsawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
A typical Beam driver program works as follows
- Create a
68 object and set the pipeline execution options, including the Pipeline Runnerawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- Create an initial
73 for pipeline data, either using the IOs to read data from an external storage system, or using aawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
94 transform to build aawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
73 from in-memory dataawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- Apply
78s to eachawait 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 aawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
73. A transform creates a new outputawait 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 outputawait 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 ofawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
73s as variables andawait 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 graphawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- Use IOs to write the final, transformed
73[s] to an external sourceawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- 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-end2. 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 objectA 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 system2. 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ụ sauSử 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ọiBấ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[];
17PipelineOptions 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
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ốPipelineOptions options = PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
Building your
PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 this way lets you specify any of the options as a command-line argumentDefining 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ẩnTo add your own options, define an interface with getter and setter methods for each option
The following example shows how to addPipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
21 and PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
22 custom optionspublic 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
0import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
1import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
2You 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 valueYou 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
3import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
4import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
5For 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 optionsThe following example code shows how to register your custom options interface with
PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
6Now your pipeline can accept
PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
31 and PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
32 as command-line arguments3. PCollections
The PCollection
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.
}];
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 pipeline3. 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 purposes3. 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 sourceEach 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
7import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
8import 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[]
0See 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 itselfAs 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 itselfTo 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 transformTo 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 objectMã 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[]
43. 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ần3. 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ơn3. 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 đầuGhi 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
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 DoFnawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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úcBeam 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ày3. 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àoGhi chú. Các nguồn tạo ra một
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 [await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
21]from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
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 producesAggregation 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 case4. 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[]
8Bở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[]
9await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
0await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
1await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
2The 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 soawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
3await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
4await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
5await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
6The 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[]
52PTransforms 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 construction4. 2. Core Beam transforms
Beam provides the following core transforms, each of which represents a different processing paradigm
56from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
14from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
47from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
15from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
46from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
61from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
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 itself4. 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.
}];
73from 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
56 to consider each element in afrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
73 and either output that element to a new collection or discard itawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- Formatting or type-converting each element in a data set. If your input
73 contains elements that are of a different type or format than you want, you can useawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
56 to perform a conversion on each element and output the result to a newfrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
73await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- Extracting parts of each element in a data set. If you have a
73 of records with multiple fields, for example, you can use aawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
56 to parse out just the fields you want to consider into a newfrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
73await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- Performing computations on each element in a data set. You can use
56 to perform simple or complex computations on every element, or certain elements, of afrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
73 and output the results as a newawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
73await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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 functionWhen you create a subclass of
83, note that your subclass should adhere to thefrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
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 reflectionawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
74. 2. 1. 1. Applying ParDoLike 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 codefrom 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 codeawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
8await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
9PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
0PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
1In 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 DoFnThe
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 tasksNote. Khi bạn tạo
83 của mình, hãy lưu ý và đảm bảo rằng mã của bạn tuân theo chúngfrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
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 thisA
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àyPipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
2PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
3Inside 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 insteadInside 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 behaviorFor 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 errorPipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
4PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
5PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
6PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
7Simple DoFns can also be written as functions
PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
8Ghi chú. Whether using a structural
83 type or a functionalfrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
83, they should be registered with beam in anfrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
45 block. Otherwise they may not execute on distributed runners.// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
Ghi chú. Nếu các thành phần trong dữ liệu đầu vào của bạn
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àawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
47 hoặc// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
48.// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
Ghi chú. Nếu các phần tử trong đầu vào của bạn
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ộtawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
50// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
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 invocationsIn 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
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].// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
- Once you output a value using
54 you should not modify that value in any way// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
- You should not in any way modify the
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.// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
- Once you output a value using
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// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
- Bạn không nên sửa đổi các tham số được cung cấp cho phương thức
39 hoặc bất kỳ đầu vào phụ nào theo bất kỳ cách nào.// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
- Once you output a value using an
50, you should not modify that value in any way// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
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[];
9from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
0from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
1from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
2If 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
69 // If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
70a direct return . // If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
3from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
4from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
5from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
6Note. You can use Java 8 lambda functions with several other Beam transforms, including
74,// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
75, and// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
61.from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
4. 2. 1. 4. DoFn lifecycleGhi 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
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// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
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 keyfrom 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 appearsOur 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 collectionfrom apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
7from 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 thisfrom apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
8Thus,
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
14 is straightforwardfrom apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
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 groupingfrom 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[]
24. 2. 2. 1 GroupByKey and unbounded PCollectionsIf 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ạnIf 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 timeWhen 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 secondsIf 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 time4. 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 joinConsider 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 nameIf 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 detailsIn 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 collectionIn 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.
}];
73In 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[]
47Cá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[]
47The 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 numbersThe 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[]
6After
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[]
9const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
0The 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 collectionThe 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 inputsconst pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
1const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
2const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
3const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
4The 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];
5const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
6const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
7const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
84. 2. 4. Combine
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[]
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 maxSimple 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
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 accumulatorsconst pipeline_options = { runner: "default", project: "my_project", }; const runner = beam.createRunner[pipeline_options]; const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
The following example code shows a simple combine function. Combining is done by modifying a grouping transform with the
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];
const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
9--=
0--=
1--=
2All 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 reflectionCombiner1 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/outputCombiner2 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 typeCombiner3 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 output4. 2. 4. 2. Advanced combinations using CombineFnFor 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. 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
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
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
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--=
64. 2. 4. 3. Combining a PCollection into a single valueNote. Only
83 is a required method. The others will have a default interpretation based on the accumulator typeconst pipeline_options = { runner: "default", project: "my_project", }; const runner = beam.createRunner[pipeline_options]; const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
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--=
9public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
04. 2. 4. 4. Combine and global windowingIf 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 valueTo 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 examplepublic interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
1public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
2public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
3public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
44. 2. 4. 5. Combine and non-global windowingIf 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
92, trong đó các cửa sổ trống trong đầu vàoconst pipeline_options = { runner: "default", project: "my_project", }; const runner = beam.createRunner[pipeline_options]; const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
73 cũng sẽ trống trong bộ sưu tập đầu raawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- Specify
98, in which the output is immediately converted to aconst 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’sconst pipeline_options = { runner: "default", project: "my_project", }; const runner = beam.createRunner[pipeline_options]; const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
15 is to be used as a side input later in the pipelinefrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
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 collection4. 2. 4. 6. Combining values in a keyed PCollectionAfter 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 thispublic interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
5In 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];
}
6public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
7public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
8public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
94. 2. 5. Flatten
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 from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
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 objectsimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
00import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
01import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
02import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
034. 2. 5. 1. Data encoding in merged collectionsBy 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 language4. 2. 5. 2. Merging windowed collectionsWhen 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 secondsIf 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 constructed4. 2. 6. Partition
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 from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
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 usefrom 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 groupsimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
04import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
05import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
06import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
074. 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
83[a function object used with the transform],from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
64 [a function object used with the transform], andconst pipeline_options = { runner: "default", project: "my_project", }; const runner = beam.createRunner[pipeline_options]; const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
45 [a function object used with the transform].--=
Ghi chú. Những yêu cầu này áp dụng cho
83s [một đối tượng hàm được sử dụng với biến đổi],from apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
64s [một đối tượng hàm được sử dụng với biến đổi] vàconst pipeline_options = { runner: "default", project: "my_project", }; const runner = beam.createRunner[pipeline_options]; const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
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
83, from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
64, and const pipeline_options = {
runner: "default",
project: "my_project",
};
const runner = beam.createRunner[pipeline_options];
const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
45, already implement --=
52; however, your subclass must not add any non-serializable members. Funcs are serializable as long as they are registered with --=
77 [for simple functions] or // If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
54 [for structural DoFns], and are not closures. Structural --=
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 from apache_beam.options.pipeline_options import PipelineOptions
beam_options = PipelineOptions[]
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 elementSide 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ạnAll side input iterables should be registered using a generic
--=
70 function. This optimizes runtime execution of the iterable4. 4. 1. Passing side inputs to ParDo
import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
08import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
09import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
10import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
114. 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 timeIf 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 togetherWhile
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 --=
95While
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.
}];
73s4. 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 instanceThe 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
12import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
13import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
14import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
154. 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 emitterAll 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 emitterDoFns 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
16import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
17import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
18import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
194. 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àoIn 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 orderIn 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 inputsIn 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 ordercontext. 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 methodimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
20Timestamp. 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 exampleTimestamp. 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 exampleTimestamp. 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 exampleTimestamp. 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 argumentimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
21import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
22import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
23import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
24Window. 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];
}
25Window. 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 windowWindow. Để 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];
}
32Window. 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 windowimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
25import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
26import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
27import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
28PaneInfo. 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 keyPaneInfo. 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 17821PaneInfo. 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àyWindow. Để 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 keyimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
29import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
30import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
31import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
32PipelineOptions. 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 parameterimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
33public 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 postTimer 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
34import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
35import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
364. 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 understandThe 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
57 method, the The public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
public interface MyOptions extends PipelineOptions {
String getInput[];
void setInput[String input];
String getOutput[];
void setOutput[String output];
}
54 transform applies the following transform operations. - It applies a
56 on the inputfrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
73 of text lines, producing an outputawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
73 of individual wordsawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
- It applies the Beam SDK library transform
62 on thepublic interface MyOptions extends PipelineOptions { String getInput[]; void setInput[String input]; String getOutput[]; void setOutput[String output]; }
73 of words, producing aawait 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 dataawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
37import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
38import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
39import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
40Note. Because
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 transformpublic interface MyOptions extends PipelineOptions { String getInput[]; void setInput[String input]; String getOutput[]; void setOutput[String output]; }
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 SDKFor 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 parameterTo 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.
}];
78To 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 functionsThe 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[]
00simport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
41import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
42import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
39Within 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 valueThe 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 exampleThe 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 pipelineimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
44import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
42import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
46As 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 librariesYour 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 necessaryYour 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 pipeline4. 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 pipelineimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
47import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
48import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
495. 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ạnimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
50import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
51import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
525. 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 địnhimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
53import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
54import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
55To 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.
}];
735. 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
56import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
57import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
585. 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 STRINGcountrySTRINGpostCodeSTRINGTransaction
Field NameField TypebankSTRINGpurchaseAmountDOUBLEPurchase 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 types6. 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
59import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
60import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
61import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
62Using 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 classimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
63So if we had two
await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
73s as followsimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
64Then 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 validimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
65and
import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
66Even 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 below6. 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 BeamTypeDescriptionBYTEAn 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 arrayA 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
14]. The repeated elements can have any supported typefrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
- 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ư sauTrong 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ư sauTrong 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
67import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
68import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
696. 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
025Currently 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
026EnumerationTypeThis 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
70The 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
71Given 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
72Automatic schema inference from Java POJOs and JavaBeans automatically converts Java enums to EnumerationType logical types
OneOfTypeThis 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
73The 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
74In 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 schemas6. 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 declaredBeam 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 itselfJava 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 fieldsFor 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
039import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
75The
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 constructorThere 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 recordsIn 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
76Java 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 exampleimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
77The
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 omittedimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
78import 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 classesAutoValue
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
79This 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.
}];
73simport 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 inferredBeam 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 exampleimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
80chù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
056import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
81Sometimes 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
82Note 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
057import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
83Beam 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
84Unexported 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
85Overriding 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 expressionBeam 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 fieldsIn 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
86import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
87Nested fieldsSupport 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
88WildcardsSupport 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
89ArraysAn 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
90Will 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
MapsA 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
91Support 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àoOften 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ư sauimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
92Support 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 schemaField 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
93Hỗ 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 STRINGcountrySTRINGpostCodeSTRINGWhen 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
94Support 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 fieldAnother 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
95Support 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]
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 performedThe
// 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 performedThe 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 exampleThe 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 exampleimport apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
96import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
97Support 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
98It 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[]
00Support 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 schemaJoinsBeam 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 keywordSupport 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[]
01The 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[]
02In addition to inner joins, the Join transform supports full outer joins, left outer joins, and right outer joins
Complex joinsWhile 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 keySupport for joins hasn’t been developed for the Python SDK yet
Support for joins hasn’t been developed for the Go SDK yet
Filtering eventsThe
// 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[]
03Will produce all purchases made from Germany with a purchase price of greater than twenty cents
Adding fields to a schemaThe 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[]
04Results 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 fieldRemoving fields from a schemaimport 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 syntaxFor 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[]
05Results in a copy of the input with those two fields and their corresponding values removed
Renaming schema fieldsimport 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 syntaxFor 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[]
06Results 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 typesAs 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[]
07Beam 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
095Since 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[]
08Nế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[]
09In 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 functionalityInput conversionBeam 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[]
10If 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[]
11Even 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 errorSince 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[]
12Input selectionVì đầ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[]
13You 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[]
14For 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 decodedNote 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
56 orfrom apache_beam.options.pipeline_options import PipelineOptions beam_options = PipelineOptions[]
69// If beamx or Go flags are used, flags must be parsed first, // before beam.Init[] is called. flag.Parse[]
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 packageIn 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 packageStandard 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 packageStandard 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 caseNote 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 typeYou 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.
}];
73Beam 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.
}];
73Each 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 typeThe 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 typeThe 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
123By 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 coderNote. If you create your
73 from in-memory data by using theawait 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 registeredawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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.
}];
947. 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 typeimport 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 CoderintVarIntCoderfloatFloatCoderstrBytesCoderbytesStrUtf8CoderTupleTupleCoder7. 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 typeYou 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 type7. 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 overrideMã 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[]
177. 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 drawbacksIt is inefficient in encoding size and speed. See this comparison of Java serialization methods
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[]
18If 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[]
19The 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 sizeA 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 information8. 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 íchIn 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 windowCaution. 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 fail8. 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 belowFigure 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 window8. 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 windowTo 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 pipelineFigure 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 collectionIn 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 keyLư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ấtNow, 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 collectionAs 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 window8. 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 needNote 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 window8. 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 intervalA 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 onFigure 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.
}];
73You 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.
}];
738. 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 windowWhen 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 information8. 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[]
238. 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[]
278. 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[]
31Lư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[]
358. 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ácTuy 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ơnCấ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ộn8. 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[]
38When 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
3148. 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.
}];
73Bạ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 đã đặtMộ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[]
419. 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[]
449. 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ễ đếnTuy 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ầu9. 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,
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.import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
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
244import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
341import 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 modeBạ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[]
479. 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
363To 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
367Hã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
73 sử dụng cửa sổ thời gian cố định 10 phútawait 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ử đếnawait beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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ự
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[]
499. 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
372 import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
373 when you set your windowing function: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[]
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
379 quaimport 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
381import 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ợpimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
382 vớiimport 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ạiimport 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 triggerimport 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ạtimport 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ạtimport 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ữaimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
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 sauTheo ướ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[]
559. 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[]
5710. 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
392Trong 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ênPhả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[]
59Phâ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[]
61má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[]
6310. 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 địnhimport 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[]
6510. 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[]
6710. 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ạiCử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ácTrong 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áiIn 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áiTrong 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áiGhi 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ấyGhi 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[]
69Beam 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[]
73Kế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[]
76Tú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[]
78import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
3511. 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[]
82Tuy 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[]
8311. 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[]
8611. 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[]
8611. 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ậpTrong 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[]
8611. 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 đặtTrong 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[]
93Vấ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[]
8611. 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ácTấ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[]
99Trạ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ác11. 4. 1. Sử dụng bộ hẹn giờ để thu gom rácTrong 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.
}];
00await 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[]
8611. 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.
}];
03await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
0411. 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.
}];
05await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
0612. Có thể chia tách await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
67
await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
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ống12. 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
- 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]
- 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]
- 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
- 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ụngThe 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- OffsetRangeTracker
- GrowableOffsetRangeTracker
- 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 PythonGo also has a built-in
import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
446 type- 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
451The 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ụngCô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- Thủ công
- tăng đơn điệu
- 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 PythonCá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[]
83await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
07await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
08await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
09Tạ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.
}];
10await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
11await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
1212. 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.
}];
13await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
14await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
1512. 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.
}];
16await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
17await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
1812. 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.
}];
19await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
20await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
2112. 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.
}];
22await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
23await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
2412. 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ạiawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
25await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
26await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
2712. 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 caseawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
28await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
29await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
3013. Đườ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
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
- 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
- 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
- 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
- Bắt đầu một dịch vụ mở rộng, sử dụng tùy chọn
462 để chuyển đường dẫn đến danh sách cho phépimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
- 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ậtawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
32Bướ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.
}];
33Bắ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ấpBướ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ớpCá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ênawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
34Bạ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ộngTriển khai các giao diện
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
470 và ghi đè phương thứcimport 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ứcimport 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 khaiimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
470import apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
Ghi chú.
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 Javaimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
35await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
Để biết các ví dụ đầy đủ, hãy xem JavaCountBuilder và JavaPrefixBuilder
Lưu ý rằng phương pháp
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 đổiimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
Đă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
471. Bạn phải chú thích lớp của mình bằng chú thíchimport 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ộngimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
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
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
36await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
Để 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 địnhBắ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.
}];
37Dị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
Tạo một mô-đun Python cho [các] biến đổi ngôn ngữ chéo của bạn
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
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]import apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
Trong ví dụ sau, kafka. py uses
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ướcimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
38await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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
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]
Trong mô-đun Python của bạn, khởi tạo
484 với mục tiêu Gradleimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
39await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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
497await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
40Ghi chú.
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 raimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
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
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
41await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
Đố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
42await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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
43await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
As with other Python transforms, define a
501 method that returns the URNimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
44await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
Xác định một phương thức tĩnh
502 trả về một khởi tạo của biến đổi Python đa ngôn ngữimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
45await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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
Tạo một môi trường ảo và cài đặt Apache Beam SDK
Bắt đầu dịch vụ mở rộng của SDK Python với một cổng được chỉ định
46await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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
47await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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ỉ
503import apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
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à
504import apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
- đị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
505 cho việc nàyimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
- đị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.
}];
4813. 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
506import apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
- Một biến đổi được cung cấp với Apache Beam đọc từ Kafka với siêu dữ liệu
507import apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
- Một chuyển đổi được phát triển bởi tổ chức abc. org đọc từ kho dữ liệu MyDatastore
508import apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
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ấtSử 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.
}];
49Sử 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 đíchawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
50Sử dụng lớp bên ngoài
Đả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
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
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
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.
}];
51Sử 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Đả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
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
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ộngimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
Đố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
Include
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 choimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
485import apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
52await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
Để biết thêm ví dụ, hãy xem addprefix. py và javacount. py
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.
}];
53Phươ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
521Cũ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.
}];
54Sử 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Đả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
Đả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
Sử dụng chức năng
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ênimport apache_beam as beam with beam.Pipeline[] as pipeline: pass # build your pipeline here
55await beam.createRunner[].run[function pipeline[root] { // Use root to build a pipeline. }];
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.
}];
56Lư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. gawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
57Coder 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.
}];
58Chuyể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.
}];
5913. 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.
}];
60DoFn 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.
}];
61Note 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 xemTrong 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.
}];
6214. 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
534await beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
63Khi 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[]
3014. 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.
}];
6414. 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áccụ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
550import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
551import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
060import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
553câ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
550import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
060PipelineOptions options =
PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
83import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
560import apache_beam as beam
with beam.Pipeline[] as pipeline:
pass # build your pipeline here
561Cá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ìnhawait beam.createRunner[].run[function pipeline[root] {
// Use root to build a pipeline.
}];
6514. 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