You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by tz...@apache.org on 2020/02/23 16:29:21 UTC
[flink-statefun] 02/03: [FLINK-16226] [remote] Use maxBatchSize in
HttpFunction
This is an automated email from the ASF dual-hosted git repository.
tzulitai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink-statefun.git
commit 67a3b3185adf27e14b49344616b75352b1119275
Author: Igal Shilman <ig...@gmail.com>
AuthorDate: Fri Feb 21 18:32:32 2020 +0100
[FLINK-16226] [remote] Use maxBatchSize in HttpFunction
---
.../statefun/flink/core/httpfn/HttpFunction.java | 56 ++++++++++++++++++----
1 file changed, 48 insertions(+), 8 deletions(-)
diff --git a/statefun-flink/statefun-flink-core/src/main/java/org/apache/flink/statefun/flink/core/httpfn/HttpFunction.java b/statefun-flink/statefun-flink-core/src/main/java/org/apache/flink/statefun/flink/core/httpfn/HttpFunction.java
index 2b3dbcb..2412cac 100644
--- a/statefun-flink/statefun-flink-core/src/main/java/org/apache/flink/statefun/flink/core/httpfn/HttpFunction.java
+++ b/statefun-flink/statefun-flink-core/src/main/java/org/apache/flink/statefun/flink/core/httpfn/HttpFunction.java
@@ -36,6 +36,7 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
+import org.apache.flink.statefun.flink.core.backpressure.AsyncWaiter;
import org.apache.flink.statefun.flink.core.polyglot.generated.FromFunction;
import org.apache.flink.statefun.flink.core.polyglot.generated.FromFunction.InvocationResponse;
import org.apache.flink.statefun.flink.core.polyglot.generated.ToFunction;
@@ -57,9 +58,20 @@ final class HttpFunction implements StatefulFunction {
private final OkHttpClient client;
private final HttpUrl url;
+ /**
+ * A request state keeps tracks of the number of inflight & batched requests.
+ *
+ * <p>A tracking state can have one of the following values:
+ *
+ * <ul>
+ * <li>NULL - there is no inflight request, and there is nothing in the backlog.
+ * <li>0 - there's an inflight request, but nothing in the backlog.
+ * <li>{@code > 0} There is an in flight request, and @requestState items in the backlog.
+ * </ul>
+ */
@Persisted
- private final PersistedValue<Boolean> hasInFlightRpc =
- PersistedValue.of("inflight", Boolean.class);
+ private final PersistedValue<Integer> requestState =
+ PersistedValue.of("request-state", Integer.class);
@Persisted
private final PersistedAppendingBuffer<ToFunction.Invocation> batch =
@@ -89,12 +101,28 @@ final class HttpFunction implements StatefulFunction {
private void onRequest(Context context, Any message) {
Invocation.Builder invocationBuilder = singeInvocationBuilder(context, message);
- if (hasInFlightRpc.getOrDefault(Boolean.FALSE)) {
- batch.append(invocationBuilder.build());
+ int inflightOrBatched = requestState.getOrDefault(-1);
+ if (inflightOrBatched < 0) {
+ // no inflight requests, and nothing in the batch.
+ // so we let this request to go through, and change state to indicate that:
+ // a) there is a request in flight.
+ // b) there is nothing in the batch.
+ requestState.set(0);
+ sendToFunction(context, invocationBuilder);
return;
}
- hasInFlightRpc.set(Boolean.TRUE);
- sendToFunction(context, invocationBuilder);
+ // there is at least one request in flight (inflightOrBatched >= 0),
+ // so we add that request to the batch.
+ batch.append(invocationBuilder.build());
+ inflightOrBatched++;
+ requestState.set(inflightOrBatched);
+ if (isMaxBatchSizeExceeded(inflightOrBatched)) {
+ // we are at capacity, can't add anything to the batch.
+ // we need to signal to the runtime that we are unable to process any new input
+ // and we must wait for our in flight asynchronous operation to complete before
+ // we are able to process more input.
+ ((AsyncWaiter) context).awaitAsyncOperationComplete();
+ }
}
private void onAsyncResult(
@@ -109,9 +137,17 @@ final class HttpFunction implements StatefulFunction {
handleInvocationResponse(context, invocationResult);
InvocationBatchRequest.Builder nextBatch = getNextBatch();
if (nextBatch == null) {
- hasInFlightRpc.clear();
+ // the async request was completed, and there is nothing else in the batch
+ // so we clear the requestState.
+ requestState.clear();
return;
}
+ // an async request was just completed, but while it was in flight we have
+ // accumulated a batch, we now proceed with:
+ // a) clearing the batch from our own persisted state (the batch moves to the async operation
+ // state)
+ // b) sending the accumulated batch to the remote function.
+ requestState.set(0);
batch.clear();
sendToFunction(context, nextBatch);
}
@@ -176,7 +212,6 @@ final class HttpFunction implements StatefulFunction {
// --------------------------------------------------------------------------------
// Send Message to Remote Function
// --------------------------------------------------------------------------------
-
/**
* Returns an {@link Invocation.Builder} set with the input {@code message} and the caller
* information (is present).
@@ -237,4 +272,9 @@ final class HttpFunction implements StatefulFunction {
IOUtils.closeQuietly(httpResponseBody);
}
}
+
+ private boolean isMaxBatchSizeExceeded(final int currentBatchSize) {
+ int maxBatchSize = functionSpec.maxBatchSize();
+ return maxBatchSize > 0 && currentBatchSize >= maxBatchSize;
+ }
}