summaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2020-06-04 14:35:50 +0200
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2020-06-15 13:18:01 +0200
commite8e7fd87ca37947df4bbf1633d66ebc6dbba7596 (patch)
tree8c27b594ef93e7542cd40f45105f1c514e930f65 /config-model
parent2e86091b55d26a7e15aa1885490c329eceedfc1c (diff)
Use separate threadpools for feeding APIs
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java76
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java10
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java5
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java2
4 files changed, 70 insertions, 23 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java b/config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java
index 58f03bffb30..9ee62aca798 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java
@@ -5,46 +5,92 @@ import com.yahoo.config.model.producer.AbstractConfigProducer;
import com.yahoo.container.bundle.BundleInstantiationSpecification;
import com.yahoo.osgi.provider.model.ComponentModel;
import com.yahoo.vespa.model.container.ContainerCluster;
+import com.yahoo.vespa.model.container.ThreadPoolExecutorComponent;
import com.yahoo.vespa.model.container.component.Handler;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
/**
* @author Einar M R Rosenvinge
+ * @author bjorncs
*/
public class ContainerDocumentApi {
- private static final String vespaClientBundleSpecification = "vespaclient-container-plugin";
- private final Options options;
+ private static final int FALLBACK_MAX_POOL_SIZE = 0; // Use fallback based on actual logical core count on host
+ private static final int FALLBACK_CORE_POOL_SIZE = 0; // Use fallback based on actual logical core count on host
- public ContainerDocumentApi(ContainerCluster cluster, Options options) {
- this.options = options;
- setupHandlers(cluster);
+ public ContainerDocumentApi(ContainerCluster<?> cluster, Options options) {
+ setupHandlers(cluster, options);
}
- private void setupHandlers(ContainerCluster cluster) {
- cluster.addComponent(newVespaClientHandler("com.yahoo.document.restapi.resource.RestApi", "document/v1/*"));
- cluster.addComponent(newVespaClientHandler("com.yahoo.vespa.http.server.FeedHandler", ContainerCluster.RESERVED_URI_PREFIX + "/feedapi"));
+ private static void setupHandlers(ContainerCluster<?> cluster, Options options) {
+ addRestApiHandler(cluster, options);
+ addFeedHandler(cluster, options);
}
- private Handler<AbstractConfigProducer<?>> newVespaClientHandler(String componentId, String bindingSuffix) {
- Handler<AbstractConfigProducer<?>> handler = new Handler<>(new ComponentModel(
- BundleInstantiationSpecification.getFromStrings(componentId, null, vespaClientBundleSpecification), ""));
+ private static void addFeedHandler(ContainerCluster<?> cluster, Options options) {
+ var executorComponent = newExecutorComponent("feedapi-handler", cluster, options);
+ String bindingSuffix = ContainerCluster.RESERVED_URI_PREFIX + "/feedapi";
+ var handler = newVespaClientHandler(
+ "com.yahoo.vespa.http.server.FeedHandler", bindingSuffix, options, executorComponent);
+ cluster.addComponent(handler);
+ }
+
+ private static void addRestApiHandler(ContainerCluster<?> cluster, Options options) {
+ var executorComponent = newExecutorComponent("restapi-handler", cluster, options);
+ var handler = newVespaClientHandler(
+ "com.yahoo.document.restapi.resource.RestApi", "document/v1/*", options, executorComponent);
+ cluster.addComponent(handler);
+ }
+
+ private static ThreadPoolExecutorComponent newExecutorComponent(String name, ContainerCluster<?> cluster, Options options) {
+ int maxPoolSize = maxPoolSize(cluster);
+ return new ThreadPoolExecutorComponent.Builder(name)
+ .maxPoolSize(maxPoolSize)
+ .corePoolSize(corePoolSize(maxPoolSize, options))
+ .queueSize(500)
+ .build();
+ }
+ private static Handler<AbstractConfigProducer<?>> newVespaClientHandler(
+ String componentId,
+ String bindingSuffix,
+ Options options,
+ ThreadPoolExecutorComponent executorComponent) {
+ Handler<AbstractConfigProducer<?>> handler = new Handler<>(new ComponentModel(
+ BundleInstantiationSpecification.getFromStrings(componentId, null, "vespaclient-container-plugin"), ""));
for (String rootBinding : options.bindings) {
- handler.addServerBindings(rootBinding + bindingSuffix,
- rootBinding + bindingSuffix + '/');
+ handler.addServerBindings(rootBinding + bindingSuffix, rootBinding + bindingSuffix + '/');
}
+ handler.addComponent(executorComponent);
return handler;
}
+ private static int maxPoolSize(ContainerCluster<?> cluster) {
+ List<Double> vcpus = cluster.getContainers().stream()
+ .map(c -> c.getHostResource().realResources().vcpu())
+ .distinct()
+ .collect(Collectors.toList());
+ // We can only use host resource for calculation if all container nodes in the cluster are homogeneous (in terms of vcpu)
+ if (vcpus.size() != 1 || vcpus.get(0) == 0) return FALLBACK_MAX_POOL_SIZE;
+ return (int)Math.ceil(vcpus.get(0));
+ }
+
+ private static int corePoolSize(int maxPoolSize, Options options) {
+ if (maxPoolSize == FALLBACK_MAX_POOL_SIZE) return FALLBACK_CORE_POOL_SIZE;
+ return (int) Math.ceil(options.feedCoreThreadPoolSizeFactor * maxPoolSize);
+ }
+
public static final class Options {
private final Collection<String> bindings;
+ private final double feedCoreThreadPoolSizeFactor;
-
- public Options(Collection<String> bindings) {
+ public Options(Collection<String> bindings, double feedCoreThreadPoolSizeFactor) {
this.bindings = Collections.unmodifiableCollection(bindings);
+ this.feedCoreThreadPoolSizeFactor = feedCoreThreadPoolSizeFactor;
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
index b83632a58a0..2966e0e000d 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
@@ -192,7 +192,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
addProcessing(deployState, spec, cluster);
addSearch(deployState, spec, cluster);
addDocproc(deployState, spec, cluster);
- addDocumentApi(spec, cluster); // NOTE: Must be done after addSearch
+ addDocumentApi(deployState, spec, cluster); // NOTE: Must be done after addSearch
cluster.addDefaultHandlersExceptStatus();
addStatusHandlers(cluster, context.getDeployState().isHosted());
@@ -409,8 +409,8 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
cluster.addServlet(new ServletBuilder().build(deployState, cluster, servletElem));
}
- private void addDocumentApi(Element spec, ApplicationContainerCluster cluster) {
- ContainerDocumentApi containerDocumentApi = buildDocumentApi(cluster, spec);
+ private void addDocumentApi(DeployState deployState, Element spec, ApplicationContainerCluster cluster) {
+ ContainerDocumentApi containerDocumentApi = buildDocumentApi(deployState, cluster, spec);
if (containerDocumentApi == null) return;
cluster.setDocumentApi(containerDocumentApi);
@@ -839,11 +839,11 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
return result.toArray(new String[result.size()]);
}
- private ContainerDocumentApi buildDocumentApi(ApplicationContainerCluster cluster, Element spec) {
+ private ContainerDocumentApi buildDocumentApi(DeployState deployState, ApplicationContainerCluster cluster, Element spec) {
Element documentApiElement = XML.getChild(spec, "document-api");
if (documentApiElement == null) return null;
- ContainerDocumentApi.Options documentApiOptions = DocumentApiOptionsBuilder.build(documentApiElement);
+ ContainerDocumentApi.Options documentApiOptions = DocumentApiOptionsBuilder.build(deployState, documentApiElement);
return new ContainerDocumentApi(cluster, documentApiOptions);
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java
index ae74dbdb4a7..bbeeffda612 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/DocumentApiOptionsBuilder.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.container.xml;
+import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.text.XML;
import com.yahoo.vespa.model.clients.ContainerDocumentApi;
import org.w3c.dom.Element;
@@ -20,8 +21,8 @@ public class DocumentApiOptionsBuilder {
private static final Logger log = Logger.getLogger(DocumentApiOptionsBuilder.class.getName());
private static final String[] DEFAULT_BINDINGS = {"http://*/"};
- public static ContainerDocumentApi.Options build(Element spec) {
- return new ContainerDocumentApi.Options(getBindings(spec));
+ public static ContainerDocumentApi.Options build(DeployState deployState, Element spec) {
+ return new ContainerDocumentApi.Options(getBindings(spec), deployState.getProperties().feedCoreThreadPoolSizeFactor());
}
private static List<String> getBindings(Element spec) {
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java
index ac2e1b88c0b..26154808580 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java
@@ -24,7 +24,7 @@ import static org.junit.Assert.assertThat;
public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBase {
private Map<String, Handler<?>> getHandlers(String clusterName) {
- ContainerCluster cluster = (ContainerCluster) root.getChildren().get(clusterName);
+ ContainerCluster<?> cluster = (ContainerCluster<?>) root.getChildren().get(clusterName);
Map<String, Handler<?>> handlerMap = new HashMap<>();
Collection<Handler<?>> handlers = cluster.getHandlers();
for (Handler<?> handler : handlers) {