Skip to content

Commit

Permalink
Support configuring minThreads and maxThreads (#722)
Browse files Browse the repository at this point in the history
  • Loading branch information
andriy-dmytruk authored May 31, 2024
1 parent 749ed8e commit 86de754
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 6 deletions.
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;
}
}

0 comments on commit 86de754

Please sign in to comment.