diff options
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, |