Update WebMvc docs on use of AsyncTaskExecutor

Closes gh-30905
This commit is contained in:
rstoyanchev
2023-07-18 10:42:27 +01:00
parent 4becce1c2b
commit 73c06347be
3 changed files with 17 additions and 21 deletions

View File

@@ -92,7 +92,7 @@ Kotlin::
====== ======
The return value can then be obtained by running the given task through the The return value can then be obtained by running the given task through the
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[configured] `TaskExecutor`. xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[configured] `AsyncTaskExecutor`.
@@ -128,7 +128,7 @@ Here is a very concise overview of Servlet asynchronous request processing:
* The controller returns a `Callable`. * The controller returns a `Callable`.
* Spring MVC calls `request.startAsync()` and submits the `Callable` to * Spring MVC calls `request.startAsync()` and submits the `Callable` to
a `TaskExecutor` for processing in a separate thread. an `AsyncTaskExecutor` for processing in a separate thread.
* Meanwhile, the `DispatcherServlet` and all filters exit the Servlet container thread, * Meanwhile, the `DispatcherServlet` and all filters exit the Servlet container thread,
but the response remains open. but the response remains open.
* Eventually the `Callable` produces a result, and Spring MVC dispatches the request back * Eventually the `Callable` produces a result, and Spring MVC dispatches the request back
@@ -404,11 +404,10 @@ TIP: Spring MVC supports Reactor and RxJava through the
For streaming to the response, reactive back pressure is supported, but writes to the For streaming to the response, reactive back pressure is supported, but writes to the
response are still blocking and are run on a separate thread through the response are still blocking and are run on a separate thread through the
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[configured] `TaskExecutor`, to avoid xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[configured]
blocking the upstream source (such as a `Flux` returned from `WebClient`). `AsyncTaskExecutor`, to avoid blocking the upstream source such as a `Flux` returned
By default, `SimpleAsyncTaskExecutor` is used for the blocking writes, but that is not from `WebClient`.
suitable under load. If you plan to stream with a reactive type, you should use the
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-configuration-spring-mvc[MVC configuration] to configure a task executor.
@@ -494,7 +493,7 @@ In `web.xml` configuration, you can add `<async-supported>true</async-supported>
[[mvc-ann-async-configuration-spring-mvc]] [[mvc-ann-async-configuration-spring-mvc]]
=== Spring MVC === Spring MVC
The MVC configuration exposes the following options related to asynchronous request processing: The MVC configuration exposes the following options for asynchronous request processing:
* Java configuration: Use the `configureAsyncSupport` callback on `WebMvcConfigurer`. * Java configuration: Use the `configureAsyncSupport` callback on `WebMvcConfigurer`.
* XML namespace: Use the `<async-support>` element under `<mvc:annotation-driven>`. * XML namespace: Use the `<async-support>` element under `<mvc:annotation-driven>`.
@@ -504,10 +503,9 @@ You can configure the following:
* Default timeout value for async requests, which if not set, depends * Default timeout value for async requests, which if not set, depends
on the underlying Servlet container. on the underlying Servlet container.
* `AsyncTaskExecutor` to use for blocking writes when streaming with * `AsyncTaskExecutor` to use for blocking writes when streaming with
xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-reactive-types[Reactive Types] and for executing `Callable` instances returned from xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-reactive-types[Reactive Types] and for
controller methods. We highly recommended configuring this property if you executing `Callable` instances returned from controller methods.
stream with reactive types or have controller methods that return `Callable`, since The one used by default is not suitable for production under load.
by default, it is a `SimpleAsyncTaskExecutor`.
* `DeferredResultProcessingInterceptor` implementations and `CallableProcessingInterceptor` implementations. * `DeferredResultProcessingInterceptor` implementations and `CallableProcessingInterceptor` implementations.
Note that you can also set the default timeout value on a `DeferredResult`, Note that you can also set the default timeout value on a `DeferredResult`,

View File

@@ -22,9 +22,7 @@ import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.async.CallableProcessingInterceptor; import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor; import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
@@ -49,15 +47,15 @@ public class AsyncSupportConfigurer {
/** /**
* The provided task executor is used to: * The provided task executor is used for the following:
* <ol> * <ol>
* <li>Handle {@link Callable} controller method return values. * <li>Handle {@link Callable} controller method return values.
* <li>Perform blocking writes when streaming to the response * <li>Perform blocking writes when streaming to the response
* through a reactive (e.g. Reactor, RxJava) controller method return value. * through a reactive (e.g. Reactor, RxJava) controller method return value.
* </ol> * </ol>
* <p>By default only a {@link SimpleAsyncTaskExecutor} is used. However when * <p>If your application has controllers with such return types, please
* using the above two use cases, it's recommended to configure an executor * configure an {@link AsyncTaskExecutor} as the one used by default is not
* backed by a thread pool such as {@link ThreadPoolTaskExecutor}. * suitable for production under load.
* @param taskExecutor the task executor instance to use by default * @param taskExecutor the task executor instance to use by default
*/ */
public AsyncSupportConfigurer setTaskExecutor(AsyncTaskExecutor taskExecutor) { public AsyncSupportConfigurer setTaskExecutor(AsyncTaskExecutor taskExecutor) {

View File

@@ -399,9 +399,9 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
* Set the default {@link AsyncTaskExecutor} to use when a controller method * Set the default {@link AsyncTaskExecutor} to use when a controller method
* return a {@link Callable}. Controller methods can override this default on * return a {@link Callable}. Controller methods can override this default on
* a per-request basis by returning an {@link WebAsyncTask}. * a per-request basis by returning an {@link WebAsyncTask}.
* <p>By default a {@link SimpleAsyncTaskExecutor} instance is used. * <p>If your application has controllers with such return types, please
* It's recommended to change that default in production as the simple executor * configure an {@link AsyncTaskExecutor} as the one used by default is not
* does not re-use threads. * suitable for production under load.
*/ */
public void setTaskExecutor(AsyncTaskExecutor taskExecutor) { public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor; this.taskExecutor = taskExecutor;