Skip to content

Commit fc370c9

Browse files
authored
[FnApi Java] Add support for separate named data streams to provide bundle isolation (#38863)
* [FnApi Java] Add support for separate named data streams to provide bundle isolation. This is advertised to the runner via a new NAMED_DATA_STREAMS protocol capability. The runner is then free to assign bundles to named data streams as it chooses to isolate bundle processing from each other. Instead of single data stream from the sdk, the sdk will create a data stream for each name. The benefit of doing so is that the multiplexing currently performed on data stream messages being received allows a slow bundle to fill up buffers and block the shared stream. With separate named streams, bundles on other data streams have separate grpc flow control from the blocked stream and are not affected.
1 parent 1df5723 commit fc370c9

23 files changed

Lines changed: 417 additions & 301 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"modification": 6,
2+
"modification": 7,
33
"https://github.com/apache/beam/pull/35159": "moving WindowedValue and making an interface"
44
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"comment": "Modify this file in a trivial way to cause this test suite to run!",
3-
"modification": 4
3+
"modification": 5
44
}
Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,4 @@
11
{
2-
"https://github.com/apache/beam/pull/34902": "Introducing OutputBuilder",
3-
"https://github.com/apache/beam/pull/35213": "Eliminating getPane() in favor of getPaneInfo()",
4-
"https://github.com/apache/beam/pull/35177": "Introducing WindowedValueReceiver to runners",
5-
"comment": "Modify this file in a trivial way to cause this test suite to run",
6-
"https://github.com/apache/beam/pull/31156": "noting that PR #31156 should run this test",
7-
"https://github.com/apache/beam/pull/31798": "noting that PR #31798 should run this test",
8-
"https://github.com/apache/beam/pull/32546": "noting that PR #32546 should run this test",
9-
"https://github.com/apache/beam/pull/33267": "noting that PR #33267 should run this test",
10-
"https://github.com/apache/beam/pull/33322": "noting that PR #33322 should run this test",
11-
"https://github.com/apache/beam/pull/34123": "noting that PR #34123 should run this test",
12-
"https://github.com/apache/beam/pull/34080": "noting that PR #34080 should run this test",
13-
"https://github.com/apache/beam/pull/34155": "noting that PR #34155 should run this test",
14-
"https://github.com/apache/beam/pull/34560": "noting that PR #34560 should run this test",
15-
"https://github.com/apache/beam/pull/35159": "moving WindowedValue and making an interface",
16-
"https://github.com/apache/beam/pull/35316": "noting that PR #35316 should run this test",
17-
"https://github.com/apache/beam/pull/38011": "noting that PR #38011 should run this test"
2+
"comment": "Modify this file in a trivial way to cause this test suite to run",
3+
"modification": 1
184
}

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373

7474
* (Java) Enabled state tag encoding v2 by default for new Dataflow Streaming Engine jobs. It can be disabled by passing `--experiments=disable_streaming_engine_state_tag_encoding_v2` or `--updateCompatibilityVersion=2.74.0` pipeline option. Note that the tag encoding version cannot change during a job update. Jobs using tag encoding v2 (enabled by default for new jobs on 2.75.0+) cannot be downgraded to Beam versions prior to 2.73.0, as only versions 2.73.0 and later support tag encoding v2. ([#38705](https://github.com/apache/beam/issues/38705)).
7575
* (Python) Added instrumentation to support off-the-shelf profiling agents when launching Python SDK Harness ([#38853](https://github.com/apache/beam/issues/38853)).
76+
* (Java) Added support to the FnApi Data stream protocol allowing runners to isolate bundles slowly processing input from other bundles. ([#39001](https://github.com/apache/beam/issues/39001)).
7677

7778
## Breaking Changes
7879

model/fn-execution/src/main/proto/org/apache/beam/model/fn_execution/v1/beam_fn_api.proto

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ message RemoteGrpcPort {
120120
service BeamFnControl {
121121
// Instructions sent by the runner to the SDK requesting different types
122122
// of work.
123+
//
124+
// Header metadata has the specified keys pairs:
125+
// - "worker_id": the id of the sdk
123126
rpc Control(
124127
// A stream of responses to instructions the SDK was asked to be
125128
// performed.
@@ -130,6 +133,9 @@ service BeamFnControl {
130133

131134
// Used to get the full process bundle descriptors for bundles one
132135
// is asked to process.
136+
//
137+
// Header metadata has the specified keys pairs:
138+
// - "worker_id": the id of the sdk
133139
rpc GetProcessBundleDescriptor(GetProcessBundleDescriptorRequest) returns (
134140
ProcessBundleDescriptor) {}
135141
}
@@ -416,14 +422,22 @@ message ProcessBundleRequest {
416422
// at https://s.apache.org/beam-fn-api-control-data-embedding.
417423
Elements elements = 3;
418424

419-
// indicates that the runner has no stare for the keys in this bundle
425+
// Indicates that the runner has no state for the keys in this bundle
420426
// so SDk can safely begin stateful processing with a locally-generated
421-
// initial empty state
427+
// initial empty state.
422428
bool has_no_state = 4;
423429

424-
// indicates that the runner will never process another bundle for the keys
430+
// Indicates that the runner will never process another bundle for the keys
425431
// in this bundle so state need not be included in the bundle commit.
426432
bool only_bundle_for_keys = 5;
433+
434+
// (Optional) If non-empty, the ID of the data stream to use for all data
435+
// requests related to this bundle. See comments at BeamFnData.Data for
436+
// more details.
437+
//
438+
// The runner should only populate this field if the sdk advertises the
439+
// beam:protocol:named_data_streams:v1 capability.
440+
string data_stream_id = 6;
427441
}
428442

429443
message ProcessBundleResponse {
@@ -834,7 +848,15 @@ message Elements {
834848

835849
// Stable
836850
service BeamFnData {
837-
// Used to send data between harnesses.
851+
// Used to send data between harnesses. Sdks default to using an unnamed data stream
852+
// (without "data_stream_id" header value) for bundles unless the runner requests another named stream to be
853+
// used for a bundle. SDKs can advertise that they support named data streams with the capability
854+
// `beam:protocol:named_data_streams:v1`.
855+
//
856+
// Header metadata has the specified keys pairs:
857+
// - "worker_id": value is the id of the sdk
858+
// - "data_stream_id": value is the id of the data stream, distinguishing it from other data streams from the same
859+
// sdk. This field should only be populated if requested in a received ProcessBundleRequest from the runner.
838860
rpc Data(
839861
// A stream of data representing input.
840862
stream Elements)
@@ -900,6 +922,9 @@ message StateResponse {
900922

901923
service BeamFnState {
902924
// Used to get/append/clear state stored by the runner on behalf of the SDK.
925+
//
926+
// Header metadata has the specified keys pairs:
927+
// - "worker_id": the id of the sdk
903928
rpc State(
904929
// A stream of state instructions requested of the runner.
905930
stream StateRequest)
@@ -1295,6 +1320,9 @@ message LogControl {}
12951320
service BeamFnLogging {
12961321
// Allows for the SDK to emit log entries which the runner can
12971322
// associate with the active job.
1323+
//
1324+
// Header metadata has the specified keys pairs:
1325+
// - "worker_id": the id of the sdk
12981326
rpc Logging(
12991327
// A stream of log entries batched into lists emitted by the SDK harness.
13001328
stream LogEntry.List)
@@ -1356,6 +1384,8 @@ message WorkerStatusResponse {
13561384

13571385
// API for SDKs to report debug-related statuses to runner during pipeline execution.
13581386
service BeamFnWorkerStatus {
1387+
// Header metadata has the specified keys pairs:
1388+
// - "worker_id": the id of the sdk
13591389
rpc WorkerStatus (stream WorkerStatusResponse)
13601390
returns (stream WorkerStatusRequest) {}
13611391
}

model/pipeline/src/main/proto/org/apache/beam/model/pipeline/v1/beam_runner_api.proto

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,6 +1689,10 @@ message StandardProtocols {
16891689
// Indicates whether the SDK supports multimap state.
16901690
MULTIMAP_STATE = 12
16911691
[(beam_urn) = "beam:protocol:multimap_state:v1"];
1692+
1693+
// Indicates whether the SDK supports data stream ids being requested by the runner in
1694+
// ProcessBundleRequests.
1695+
NAMED_DATA_STREAMS = 13 [(beam_urn) = "beam:protocol:named_data_streams:v1"];
16921696
}
16931697
}
16941698

runners/java-fn-execution/src/main/java/org/apache/beam/runners/fnexecution/control/SdkHarnessClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ public ActiveBundle newBundle(
298298
ImmutableMap.Builder<LogicalEndpoint, FnDataReceiver<?>> receiverBuilder =
299299
ImmutableMap.builder();
300300
BeamFnDataOutboundAggregator beamFnDataOutboundAggregator =
301-
fnApiDataService.createOutboundAggregator(() -> bundleId, false);
301+
fnApiDataService.createOutboundAggregator(bundleId, false);
302302
for (RemoteInputDestination remoteInput : remoteInputs) {
303303
LogicalEndpoint endpoint = LogicalEndpoint.data(bundleId, remoteInput.getPTransformId());
304304
receiverBuilder.put(

runners/java-fn-execution/src/main/java/org/apache/beam/runners/fnexecution/data/FnDataService.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
*/
1818
package org.apache.beam.runners.fnexecution.data;
1919

20-
import java.util.function.Supplier;
2120
import org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements;
2221
import org.apache.beam.sdk.fn.data.BeamFnDataOutboundAggregator;
2322
import org.apache.beam.sdk.fn.data.CloseableFnDataReceiver;
@@ -69,5 +68,5 @@ public interface FnDataService {
6968
* <p>The returned aggregator is not thread safe.
7069
*/
7170
BeamFnDataOutboundAggregator createOutboundAggregator(
72-
Supplier<String> processBundleRequestIdSupplier, boolean collectElementsIfNoFlushes);
71+
String processBundleId, boolean collectElementsIfNoFlushes);
7372
}

runners/java-fn-execution/src/main/java/org/apache/beam/runners/fnexecution/data/GrpcDataService.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.util.concurrent.LinkedBlockingQueue;
2424
import java.util.concurrent.TimeUnit;
2525
import java.util.concurrent.TimeoutException;
26-
import java.util.function.Supplier;
2726
import org.apache.beam.model.fnexecution.v1.BeamFnApi;
2827
import org.apache.beam.model.fnexecution.v1.BeamFnApi.Elements;
2928
import org.apache.beam.model.fnexecution.v1.BeamFnDataGrpc;
@@ -175,13 +174,13 @@ public void unregisterReceiver(String instructionId) {
175174

176175
@Override
177176
public BeamFnDataOutboundAggregator createOutboundAggregator(
178-
Supplier<String> processBundleRequestIdSupplier, boolean collectElementsIfNoFlushes) {
177+
String instructionId, boolean collectElementsIfNoFlushes) {
179178
try {
180-
return new BeamFnDataOutboundAggregator(
181-
options,
182-
processBundleRequestIdSupplier,
183-
connectedClient.get(3, TimeUnit.MINUTES).getOutboundObserver(),
184-
collectElementsIfNoFlushes);
179+
BeamFnDataOutboundAggregator aggregator =
180+
new BeamFnDataOutboundAggregator(options, collectElementsIfNoFlushes);
181+
aggregator.prepareForInstruction(
182+
instructionId, connectedClient.get(3, TimeUnit.MINUTES).getOutboundObserver());
183+
return aggregator;
185184
} catch (InterruptedException e) {
186185
Thread.currentThread().interrupt();
187186
throw new RuntimeException(e);

runners/java-fn-execution/src/test/java/org/apache/beam/runners/fnexecution/data/GrpcDataServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public void testMessageReceivedBySingleClientWhenThereAreMultipleClients() throw
102102
for (int i = 0; i < 3; ++i) {
103103
final String instructionId = Integer.toString(i);
104104
BeamFnDataOutboundAggregator aggregator =
105-
service.createOutboundAggregator(() -> instructionId, false);
105+
service.createOutboundAggregator(instructionId, false);
106106
aggregator.start();
107107
FnDataReceiver<WindowedValue<String>> consumer =
108108
aggregator.registerOutputDataLocation(TRANSFORM_ID, CODER);

0 commit comments

Comments
 (0)