Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support configuring minThreads and maxThreads #722

Merged
merged 1 commit into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -365,17 +365,23 @@ private void applyAdditionalPorts(Server server, ServerConnector serverConnector
* @return The server
*/
protected @NonNull Server newServer(@NonNull ApplicationContext applicationContext, @NonNull MicronautServletConfiguration configuration) {
Server server;
QueuedThreadPool threadPool;
if (configuration.getMaxThreads() != null) {
if (configuration.getMinThreads() != null) {
threadPool = new QueuedThreadPool(configuration.getMaxThreads(), configuration.getMinThreads());
} else {
threadPool = new QueuedThreadPool(configuration.getMaxThreads());
}
} else {
threadPool = new QueuedThreadPool();
}

if (configuration.isEnableVirtualThreads() && LoomSupport.isSupported()) {
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setVirtualThreadsExecutor(
applicationContext.getBean(ExecutorService.class, Qualifiers.byName(TaskExecutors.BLOCKING))
);
server = new Server(threadPool);
} else {
server = new Server();
}
return server;
return new Server(threadPool);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.micronaut.servlet.jetty

import io.micronaut.context.annotation.Property
import io.micronaut.http.HttpRequest
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Produces
import io.micronaut.http.annotation.QueryValue
import io.micronaut.http.client.HttpClient
import io.micronaut.http.client.annotation.Client
import io.micronaut.servlet.engine.MicronautServletConfiguration
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import jakarta.inject.Inject
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.util.Jetty
import spock.lang.Specification

@MicronautTest
@Property(name = "spec.name", value = SPEC_NAME)
@Property(name = "micronaut.servlet.minThreads", value = "11")
@Property(name = "micronaut.servlet.maxThreads", value = "11")
class JettyConfigurationSpec extends Specification {

static final String SPEC_NAME = "JettyConfigurationSpec"

@Inject
Server jetty

@Inject
@Client("/configTest")
HttpClient client

void "configuring thread pool is supported"() {
when:
var threadPool = jetty.threadPool

then:
threadPool.threads == 11

when:
def request = HttpRequest.GET("/")
String response = client.toBlocking().retrieve(request)

then:
response == "OK"
}

@Controller("/configTest")
static class TestController {

@Get
@Produces(MediaType.TEXT_PLAIN)
String index() {
"OK"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.ContainerBase;
import org.apache.catalina.core.StandardThreadExecutor;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.http2.Http2Protocol;
Expand Down Expand Up @@ -124,6 +125,21 @@ protected Tomcat tomcatServer(
configuration.setAsyncFileServingEnabled(false);

Tomcat tomcat = newTomcat();
if (configuration.getMaxThreads() != null) {
StandardThreadExecutor executor = new StandardThreadExecutor();
executor.setName("tomcatThreadPool");
executor.setMaxThreads(configuration.getMaxThreads());
if (configuration.getMinThreads() != null) {
executor.setMinSpareThreads(configuration.getMinThreads());
}
tomcat.getService().addExecutor(executor);
if (connector != null) {
connector.getProtocolHandler().setExecutor(executor);
}
if (httpsConnector != null) {
httpsConnector.getProtocolHandler().setExecutor(executor);
}
}
final Context context = newTomcatContext(tomcat);

configureServletInitializer(context, servletInitializers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ protected Undertow.Builder undertowBuilder(DeploymentInfo deploymentInfo, Micron
applyAdditionalPorts(builder, host, port, null);
}

if (servletConfiguration.getMaxThreads() != null) {
builder.setServerOption(Options.WORKER_TASK_MAX_THREADS, servletConfiguration.getMaxThreads());
if (servletConfiguration.getMinThreads() != null) {
builder.setServerOption(Options.WORKER_TASK_CORE_THREADS, servletConfiguration.getMinThreads());
}
}
Map<String, String> serverOptions = configuration.getServerOptions();
serverOptions.forEach((key, value) -> {
Object opt = ReflectionUtils.findDeclaredField(UndertowOptions.class, key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,23 @@ default boolean isAsyncSupported() {
default boolean isEnableVirtualThreads() {
return true;
}

/**
* Get the minimum number of threads in the created thread pool.
*
* @return The minimum number of threads
*/
default Integer getMinThreads() {
return null;
}

/**
* Get the maximum number of threads in the created thread pool.
*
* @return The maximum number of threads
*/
default Integer getMaxThreads() {
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ public class MicronautServletConfiguration implements Named, ServletConfiguratio
private boolean asyncSupported = true;
private boolean enableVirtualThreads = true;

private Integer minThreads;
private Integer maxThreads;


/**
* Default constructor.
Expand Down Expand Up @@ -151,4 +154,32 @@ public void setAsyncFileServingEnabled(boolean enabled) {
public boolean isAsyncFileServingEnabled() {
return asyncSupported && asyncFileServingEnabled;
}

@Override
public Integer getMinThreads() {
return minThreads;
}

/**
* Specify the minimum number of threads in the created thread pool.
*
* @param minThreads The minimum number of threads
*/
public void setMinThreads(Integer minThreads) {
this.minThreads = minThreads;
}

@Override
public Integer getMaxThreads() {
return maxThreads;
}

/**
* Specify the maximum number of threads in the created thread pool.
*
* @param maxThreads The maximum number of threads
*/
public void setMaxThreads(Integer maxThreads) {
this.maxThreads = maxThreads;
}
}
Loading