summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2020-03-13 21:49:25 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2020-03-13 21:49:25 +0000
commit2c52421478d1e47db32ec8ff8c482f861fd93b93 (patch)
treed44c9522168f60ff81da82ec0542dd18b3d61adf
parent7e92c3852e893d09f0aa821e04e4e9dbe83b4ab2 (diff)
When you have a container with both feed and query, you risk that during warmup the throughput optimized
feed pipeline will overwhelm the search pipeline during warmup. Here we add an option to enforce a soft start of the feed pipeline, by gradually increasing max number of feed threads. It might not be the perfect solution as mesages will pile up in the dynamic throttle policy, but that should have a builtin softstart already. So I think this might a good fit.
-rw-r--r--container-core/abi-spec.json4
-rw-r--r--container-core/src/main/resources/configdefinitions/threadpool.def5
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java4
-rw-r--r--vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java20
4 files changed, 29 insertions, 4 deletions
diff --git a/container-core/abi-spec.json b/container-core/abi-spec.json
index f0d7f4068be..ce567176679 100644
--- a/container-core/abi-spec.json
+++ b/container-core/abi-spec.json
@@ -172,6 +172,7 @@
"public void <init>(com.yahoo.container.handler.ThreadpoolConfig)",
"public com.yahoo.container.handler.ThreadpoolConfig$Builder maxthreads(int)",
"public com.yahoo.container.handler.ThreadpoolConfig$Builder maxThreadExecutionTimeSeconds(int)",
+ "public com.yahoo.container.handler.ThreadpoolConfig$Builder softStartSeconds(double)",
"public final boolean dispatchGetConfig(com.yahoo.config.ConfigInstance$Producer)",
"public final java.lang.String getDefMd5()",
"public final java.lang.String getDefName()",
@@ -209,7 +210,8 @@
"public static java.lang.String getDefVersion()",
"public void <init>(com.yahoo.container.handler.ThreadpoolConfig$Builder)",
"public int maxthreads()",
- "public int maxThreadExecutionTimeSeconds()"
+ "public int maxThreadExecutionTimeSeconds()",
+ "public double softStartSeconds()"
],
"fields": [
"public static final java.lang.String CONFIG_DEF_MD5",
diff --git a/container-core/src/main/resources/configdefinitions/threadpool.def b/container-core/src/main/resources/configdefinitions/threadpool.def
index 5b5e7e2f4a2..9bb9badd9b5 100644
--- a/container-core/src/main/resources/configdefinitions/threadpool.def
+++ b/container-core/src/main/resources/configdefinitions/threadpool.def
@@ -8,3 +8,8 @@ maxthreads int default=500
# get out of a bad state. This should be set a bit higher than the expected max execution
# time of each request when in a state of overload, i.e about "worst case execution time*2"
maxThreadExecutionTimeSeconds int default=190
+
+# Length of period for soft start
+# During this period number of availble threads will be gradually increased.
+# Currently used to avoid feeding overload in container during cold start.
+softStartSeconds double default=0
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java
index ec5fc0cad07..d537e873600 100644
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java
+++ b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java
@@ -57,8 +57,8 @@ class ClientFeederV3 {
private final Object monitor = new Object();
private final StreamReaderV3 streamReaderV3;
private final AtomicInteger ongoingRequests = new AtomicInteger(0);
- private String hostName;
- private AtomicInteger threadsAvailableForFeeding;
+ private final String hostName;
+ private final AtomicInteger threadsAvailableForFeeding;
ClientFeederV3(
ReferencedResource<SharedSourceSession> sourceSession,
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java
index 37803d96714..1b342363046 100644
--- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java
+++ b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java
@@ -43,6 +43,9 @@ public class FeedHandlerV3 extends LoggingRequestHandler {
protected final ReplyHandler feedReplyHandler;
private final Metric metric;
private final Object monitor = new Object();
+ private int remainingThreadsForFeedingAllowance;
+ private final long msBetweenBumpingMaxThreads;
+ private long nextTimeToAllocateAnotherThread;
private final AtomicInteger threadsAvailableForFeeding;
private static final Logger log = Logger.getLogger(FeedHandlerV3.class.getName());
@@ -60,10 +63,20 @@ public class FeedHandlerV3 extends LoggingRequestHandler {
this.metric = parentCtx.getMetric();
// 40% of the threads can be blocking on feeding before we deny requests.
if (threadpoolConfig != null) {
- threadsAvailableForFeeding = new AtomicInteger(Math.max((int) (0.4 * threadpoolConfig.maxthreads()), 1));
+ remainingThreadsForFeedingAllowance = Math.max((int) (0.4 * threadpoolConfig.maxthreads()), 1);
+ if (threadpoolConfig.softStartSeconds() > 0.0) {
+ threadsAvailableForFeeding = new AtomicInteger(0);
+ msBetweenBumpingMaxThreads = (long)threadpoolConfig.softStartSeconds() * 1000 / remainingThreadsForFeedingAllowance;
+ } else {
+ threadsAvailableForFeeding = new AtomicInteger(remainingThreadsForFeedingAllowance);
+ remainingThreadsForFeedingAllowance = 0;
+ msBetweenBumpingMaxThreads = 0;
+ }
} else {
log.warning("No config for threadpool, using 200 for max blocking threads for feeding.");
threadsAvailableForFeeding = new AtomicInteger(200);
+ remainingThreadsForFeedingAllowance = 0;
+ msBetweenBumpingMaxThreads = 0;
}
}
@@ -78,6 +91,11 @@ public class FeedHandlerV3 extends LoggingRequestHandler {
String clientId = clientId(request);
ClientFeederV3 clientFeederV3;
synchronized (monitor) {
+ if ((remainingThreadsForFeedingAllowance > 0) && (System.currentTimeMillis() > nextTimeToAllocateAnotherThread)) {
+ threadsAvailableForFeeding.incrementAndGet();
+ remainingThreadsForFeedingAllowance --;
+ nextTimeToAllocateAnotherThread = System.currentTimeMillis() + msBetweenBumpingMaxThreads;
+ }
if (! clientFeederByClientId.containsKey(clientId)) {
SourceSessionParams sourceSessionParams = sourceSessionParams(request);
clientFeederByClientId.put(clientId,