diff options
Diffstat (limited to 'config-model/src/main/java')
11 files changed, 57 insertions, 19 deletions
diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java index 00c5f6e326f..e141826ba44 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java @@ -54,6 +54,7 @@ public class TestProperties implements ModelContext.Properties { private ApplicationRoles applicationRoles; private Quota quota = Quota.unlimited(); private boolean useAccessControlTlsHandshakeClientAuth; + private double jettyThreadpoolSizeFactor = 0.0; @Override public boolean multitenant() { return multitenant; } @Override public ApplicationId applicationId() { return applicationId; } @@ -93,6 +94,7 @@ public class TestProperties implements ModelContext.Properties { @Override public boolean tlsUseFSync() { return tlsUseFSync; } @Override public String tlsCompressionType() { return tlsCompressionType; } @Override public boolean useAccessControlTlsHandshakeClientAuth() { return useAccessControlTlsHandshakeClientAuth; } + @Override public double jettyThreadpoolSizeFactor() { return jettyThreadpoolSizeFactor; } public TestProperties setJvmGCOptions(String gcOptions) { jvmGCOptions = gcOptions; @@ -144,6 +146,9 @@ public class TestProperties implements ModelContext.Properties { this.queueSizeFactor = queueSizeFactor; return this; } + + public TestProperties setJettyThreadpoolSizeFactor(double factor) { this.jettyThreadpoolSizeFactor = factor; return this; } + public TestProperties setApplicationId(ApplicationId applicationId) { this.applicationId = applicationId; return this; 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 6b6a63af43c..e75ea26d065 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 @@ -128,13 +128,13 @@ public class ContainerDocumentApi { } private int maxPoolSize() { - double vcpu = vcpu(cluster).orElse(0); + double vcpu = cluster.vcpu().orElse(0); if (vcpu == 0) return FALLBACK_MAX_POOL_SIZE; return Math.max(2, (int)Math.ceil(vcpu * feedThreadPoolSizeFactor)); } private int minPoolSize() { - double vcpu = vcpu(cluster).orElse(0); + double vcpu = cluster.vcpu().orElse(0); if (vcpu == 0) return FALLBACK_CORE_POOL_SIZE; return Math.max(1, (int)Math.ceil(vcpu * feedThreadPoolSizeFactor * 0.5)); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java index 1d991721ea7..a7f5398c7b5 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/Container.java @@ -88,7 +88,7 @@ public abstract class Container extends AbstractService implements this.parent = parent; this.retired = retired; this.index = index; - this.defaultHttpServer = new JettyHttpServer(new ComponentId("DefaultHttpServer"), isHostedVespa); + this.defaultHttpServer = new JettyHttpServer(new ComponentId("DefaultHttpServer"), containerClusterOrNull(parent), isHostedVespa); if (getHttp() == null) { addChild(defaultHttpServer); } @@ -390,8 +390,12 @@ public abstract class Container extends AbstractService implements return containerCluster().isPresent() && containerCluster().get().rpcServerEnabled(); } - private Optional<ContainerCluster> containerCluster() { - return (parent instanceof ContainerCluster) ? Optional.of((ContainerCluster) parent) : Optional.empty(); + protected Optional<ContainerCluster> containerCluster() { + return Optional.ofNullable(containerClusterOrNull(parent)); + } + + private static ContainerCluster containerClusterOrNull(AbstractConfigProducer producer) { + return producer instanceof ContainerCluster<?> ? (ContainerCluster<?>) producer : null; } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java index 0bafd3cfdcf..57ebc215dfa 100755 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java @@ -69,6 +69,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.OptionalDouble; import java.util.Set; /** @@ -160,11 +161,14 @@ public abstract class ContainerCluster<CONTAINER extends Container> private boolean deferChangesUntilRestart = false; + private double jettyThreadpoolSizeFactor; + public ContainerCluster(AbstractConfigProducer<?> parent, String configSubId, String clusterId, DeployState deployState) { super(parent, configSubId); this.name = clusterId; this.isHostedVespa = stateIsHosted(deployState); this.zone = (deployState != null) ? deployState.zone() : Zone.defaultZone(); + this.jettyThreadpoolSizeFactor = deployState.getProperties().jettyThreadpoolSizeFactor(); componentGroup = new ComponentGroup<>(this, "component"); @@ -630,4 +634,15 @@ public abstract class ContainerCluster<CONTAINER extends Container> public boolean getDeferChangesUntilRestart() { return deferChangesUntilRestart; } + /** Effective vcpu for the containers in cluster. Use this value as scale factor for performance/resource tuning. **/ + public OptionalDouble vcpu() { + return getContainers().stream() + .filter(c -> c.getHostResource() != null && c.getHostResource().realResources() != null) + .mapToDouble(c -> c.getHostResource().realResources().vcpu()) + .max(); // Use highest vcpu as scale factor + } + + public OptionalDouble jettyThreadpoolSizeFactor() { + return jettyThreadpoolSizeFactor > 0 ? OptionalDouble.of(jettyThreadpoolSizeFactor) : OptionalDouble.empty(); + } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerThreadpool.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerThreadpool.java index 93a02833d26..5074f1ecbbe 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerThreadpool.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerThreadpool.java @@ -11,7 +11,6 @@ import com.yahoo.vespa.model.container.component.SimpleComponent; import org.w3c.dom.Element; import java.util.Optional; -import java.util.OptionalDouble; /** * Component definition for a {@link java.util.concurrent.Executor} using {@link ContainerThreadPool}. @@ -48,13 +47,6 @@ public class ContainerThreadpool extends SimpleComponent implements ContainerThr protected Optional<UserOptions> userOptions() { return Optional.ofNullable(userOptions); } protected boolean hasUserOptions() { return userOptions().isPresent(); } - protected static OptionalDouble vcpu(ContainerCluster<?> cluster) { - return cluster.getContainers().stream() - .filter(c -> c.getHostResource() != null && c.getHostResource().realResources() != null) - .mapToDouble(c -> c.getHostResource().realResources().vcpu()) - .max(); // Use highest vcpu as scale factor - } - public static class UserOptions { private final int maxThreads; private final int minThreads; diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/DefaultThreadpoolProvider.java b/config-model/src/main/java/com/yahoo/vespa/model/container/DefaultThreadpoolProvider.java index 1ebd62d6479..2db567b1460 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/DefaultThreadpoolProvider.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/DefaultThreadpoolProvider.java @@ -40,7 +40,7 @@ class DefaultThreadpoolProvider extends SimpleComponent implements ThreadpoolCon } double threadPoolSizeFactor = deployState.getProperties().threadPoolSizeFactor(); - double vcpu = ContainerThreadpool.vcpu(cluster).orElse(0); + double vcpu = cluster.vcpu().orElse(0); if (threadPoolSizeFactor <= 0 || vcpu == 0) return; // Configuration is currently identical to the search handler's threadpool diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/JettyHttpServer.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/JettyHttpServer.java index 98fde2e7859..8d55b424ad9 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/JettyHttpServer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/JettyHttpServer.java @@ -6,6 +6,7 @@ import com.yahoo.component.ComponentSpecification; import com.yahoo.container.bundle.BundleInstantiationSpecification; import com.yahoo.jdisc.http.ServerConfig; import com.yahoo.osgi.provider.model.ComponentModel; +import com.yahoo.vespa.model.container.ContainerCluster; import com.yahoo.vespa.model.container.component.SimpleComponent; import java.util.ArrayList; @@ -20,16 +21,18 @@ import static com.yahoo.component.ComponentSpecification.fromString; */ public class JettyHttpServer extends SimpleComponent implements ServerConfig.Producer { + private final ContainerCluster<?> cluster; private final boolean isHostedVespa; private final List<ConnectorFactory> connectorFactories = new ArrayList<>(); - public JettyHttpServer(ComponentId id, boolean isHostedVespa) { + public JettyHttpServer(ComponentId id, ContainerCluster<?> cluster, boolean isHostedVespa) { super(new ComponentModel( new BundleInstantiationSpecification(id, fromString("com.yahoo.jdisc.http.server.jetty.JettyHttpServer"), fromString("jdisc_http_service")) )); this.isHostedVespa = isHostedVespa; + this.cluster = cluster; final FilterBindingsProviderComponent filterBindingsProviderComponent = new FilterBindingsProviderComponent(id); addChild(filterBindingsProviderComponent); inject(filterBindingsProviderComponent); @@ -69,6 +72,17 @@ public class JettyHttpServer extends SimpleComponent implements ServerConfig.Pro .remoteAddressHeaders(List.of("x-forwarded-for", "y-ra", "yahooremoteip", "client-ip")) .remotePortHeaders(List.of("X-Forwarded-Port", "y-rp"))); } + configureJettyThreadpool(builder); + } + + private void configureJettyThreadpool(ServerConfig.Builder builder) { + if (cluster == null) return; + double vcpu = cluster.vcpu().orElse(0); + double scaleFactor = cluster.jettyThreadpoolSizeFactor().orElse(0); + if (vcpu > 0 && scaleFactor > 0) { + int threads = Math.max(8, (int) Math.ceil(vcpu * scaleFactor)); + builder.maxWorkerThreads(threads).minWorkerThreads(threads); + } } static ComponentModel providerComponentModel(final ComponentId parentId, String className) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java index 004539688e2..9b9ebedda6d 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java @@ -56,7 +56,8 @@ public class HttpBuilder extends VespaDomBuilder.DomConfigProducerBuilder<Http> Http http = new Http(filterChains); http.getBindings().addAll(bindings); - http.setHttpServer(new JettyHttpServerBuilder().build(deployState, ancestor, spec)); + ApplicationContainerCluster cluster = getContainerCluster(ancestor).orElse(null); + http.setHttpServer(new JettyHttpServerBuilder(cluster).build(deployState, ancestor, spec)); if (accessControl != null) { accessControl.configureHttpFilterChains(http); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyHttpServerBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyHttpServerBuilder.java index cc9cd61df36..7f3c5f653aa 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyHttpServerBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/JettyHttpServerBuilder.java @@ -6,6 +6,7 @@ import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.text.XML; import com.yahoo.vespa.model.builder.xml.dom.VespaDomBuilder; +import com.yahoo.vespa.model.container.ContainerCluster; import com.yahoo.vespa.model.container.http.ConnectorFactory; import com.yahoo.vespa.model.container.http.JettyHttpServer; import org.w3c.dom.Element; @@ -15,9 +16,15 @@ import org.w3c.dom.Element; */ public class JettyHttpServerBuilder extends VespaDomBuilder.DomConfigProducerBuilder<JettyHttpServer> { + private final ContainerCluster<?> cluster; + + public JettyHttpServerBuilder(ContainerCluster<?> cluster) { + this.cluster = cluster; + } + @Override protected JettyHttpServer doBuild(DeployState deployState, AbstractConfigProducer ancestor, Element http) { - JettyHttpServer jettyHttpServer = new JettyHttpServer(new ComponentId("jdisc-jetty"), deployState.isHosted()); + JettyHttpServer jettyHttpServer = new JettyHttpServer(new ComponentId("jdisc-jetty"), cluster, deployState.isHosted()); for (Element serverSpec: XML.getChildren(http, "server")) { ConnectorFactory connectorFactory = new JettyConnectorBuilder().build(deployState, ancestor, serverSpec); jettyHttpServer.addConnector(connectorFactory); 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 6fd1c9b35fb..37dd97a49b1 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 @@ -360,7 +360,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { cluster.setHttp(new Http(new FilterChains(cluster))); } if(cluster.getHttp().getHttpServer().isEmpty()) { - JettyHttpServer defaultHttpServer = new JettyHttpServer(new ComponentId("DefaultHttpServer"), cluster.isHostedVespa()); + JettyHttpServer defaultHttpServer = new JettyHttpServer(new ComponentId("DefaultHttpServer"), cluster, cluster.isHostedVespa()); cluster.getHttp().setHttpServer(defaultHttpServer); defaultHttpServer.addConnector(new ConnectorFactory("SearchServer", Defaults.getDefaults().vespaWebServicePort())); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/SearchHandler.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/SearchHandler.java index 473cfa05e64..ff6fd48c06a 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/SearchHandler.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/SearchHandler.java @@ -57,7 +57,7 @@ class SearchHandler extends ProcessingHandler<SearchChains> { if (hasUserOptions()) return; double threadPoolSizeFactor = deployState.getProperties().threadPoolSizeFactor(); - double vcpu = vcpu(cluster).orElse(0); + double vcpu = cluster.vcpu().orElse(0); if (threadPoolSizeFactor <= 0 || vcpu == 0) { builder.maxThreads(500); builder.minThreads(500); |