Add 'max_blocking' threads config value.

This commit is contained in:
Matthew Pomes 2022-05-23 18:19:57 -07:00 committed by Sergio Benitez
parent 6f223518e4
commit 47946cc55c
3 changed files with 46 additions and 21 deletions

View File

@ -73,6 +73,8 @@ pub struct Config {
/// _**Note:** Rocket only reads this value from sources in the [default /// _**Note:** Rocket only reads this value from sources in the [default
/// provider](Config::figment())._ /// provider](Config::figment())._
pub workers: usize, pub workers: usize,
/// Limit on threads to start for blocking tasks. **(default: `512`)**
pub max_blocking: usize,
/// How, if at all, to identify the server via the `Server` header. /// How, if at all, to identify the server via the `Server` header.
/// **(default: `"Rocket"`)** /// **(default: `"Rocket"`)**
pub ident: Ident, pub ident: Ident,
@ -170,6 +172,7 @@ impl Config {
address: Ipv4Addr::new(127, 0, 0, 1).into(), address: Ipv4Addr::new(127, 0, 0, 1).into(),
port: 8000, port: 8000,
workers: num_cpus::get(), workers: num_cpus::get(),
max_blocking: 512,
ident: Ident::default(), ident: Ident::default(),
limits: Limits::default(), limits: Limits::default(),
temp_dir: std::env::temp_dir().into(), temp_dir: std::env::temp_dir().into(),
@ -358,6 +361,7 @@ impl Config {
launch_info_!("address: {}", bold(&self.address)); launch_info_!("address: {}", bold(&self.address));
launch_info_!("port: {}", bold(&self.port)); launch_info_!("port: {}", bold(&self.port));
launch_info_!("workers: {}", bold(self.workers)); launch_info_!("workers: {}", bold(self.workers));
launch_info_!("max blocking threads: {}", bold(self.max_blocking));
launch_info_!("ident: {}", bold(&self.ident)); launch_info_!("ident: {}", bold(&self.ident));
launch_info_!("limits: {}", bold(&self.limits)); launch_info_!("limits: {}", bold(&self.limits));
launch_info_!("temp dir: {}", bold(&self.temp_dir.relative().display())); launch_info_!("temp dir: {}", bold(&self.temp_dir.relative().display()));
@ -451,6 +455,9 @@ impl Config {
/// The stringy parameter name for setting/extracting [`Config::workers`]. /// The stringy parameter name for setting/extracting [`Config::workers`].
pub const WORKERS: &'static str = "workers"; pub const WORKERS: &'static str = "workers";
/// The stringy parameter name for setting/extracting [`Config::max_blocking`].
pub const MAX_BLOCKING: &'static str = "max_blocking";
/// The stringy parameter name for setting/extracting [`Config::keep_alive`]. /// The stringy parameter name for setting/extracting [`Config::keep_alive`].
pub const KEEP_ALIVE: &'static str = "keep_alive"; pub const KEEP_ALIVE: &'static str = "keep_alive";

View File

@ -233,12 +233,13 @@ pub use async_trait::async_trait;
/// WARNING: This is unstable! Do not use this method outside of Rocket! /// WARNING: This is unstable! Do not use this method outside of Rocket!
#[doc(hidden)] #[doc(hidden)]
pub fn async_run<F, R>(fut: F, workers: usize, force_end: bool, name: &str) -> R pub fn async_run<F, R>(fut: F, workers: usize, sync: usize, force_end: bool, name: &str) -> R
where F: std::future::Future<Output = R> where F: std::future::Future<Output = R>
{ {
let runtime = tokio::runtime::Builder::new_multi_thread() let runtime = tokio::runtime::Builder::new_multi_thread()
.thread_name(name) .thread_name(name)
.worker_threads(workers) .worker_threads(workers)
.max_blocking_threads(sync)
.enable_all() .enable_all()
.build() .build()
.expect("create tokio runtime"); .expect("create tokio runtime");
@ -254,7 +255,7 @@ pub fn async_run<F, R>(fut: F, workers: usize, force_end: bool, name: &str) -> R
/// WARNING: This is unstable! Do not use this method outside of Rocket! /// WARNING: This is unstable! Do not use this method outside of Rocket!
#[doc(hidden)] #[doc(hidden)]
pub fn async_test<R>(fut: impl std::future::Future<Output = R>) -> R { pub fn async_test<R>(fut: impl std::future::Future<Output = R>) -> R {
async_run(fut, 1, true, "rocket-worker-test-thread") async_run(fut, 1, 32, true, "rocket-worker-test-thread")
} }
/// WARNING: This is unstable! Do not use this method outside of Rocket! /// WARNING: This is unstable! Do not use this method outside of Rocket!
@ -263,8 +264,8 @@ pub fn async_main<R>(fut: impl std::future::Future<Output = R> + Send) -> R {
// FIXME: These config values won't reflect swaps of `Rocket` in attach // FIXME: These config values won't reflect swaps of `Rocket` in attach
// fairings with different config values, or values from non-Rocket configs. // fairings with different config values, or values from non-Rocket configs.
// See tokio-rs/tokio#3329 for a necessary solution in `tokio`. // See tokio-rs/tokio#3329 for a necessary solution in `tokio`.
let config = Config::from(Config::figment()); let c = Config::from(Config::figment());
async_run(fut, config.workers, config.shutdown.force, "rocket-worker-thread") async_run(fut, c.workers, c.max_blocking, c.shutdown.force, "rocket-worker-thread")
} }
/// Executes a `future` to completion on a new tokio-based Rocket async runtime. /// Executes a `future` to completion on a new tokio-based Rocket async runtime.

View File

@ -18,10 +18,11 @@ Rocket is asked to use, it must be able to read the following configuration
values: values:
| key | kind | description | debug/release default | | key | kind | description | debug/release default |
|----------------|-------------------|-------------------------------------------------|-------------------------| |-----------------|-------------------|-------------------------------------------------|-------------------------|
| `address` | `IpAddr` | IP address to serve on | `127.0.0.1` | | `address` | `IpAddr` | IP address to serve on | `127.0.0.1` |
| `port` | `u16` | Port to serve on. | `8000` | | `port` | `u16` | Port to serve on. | `8000` |
| `workers`* | `usize` | Number of threads to use for executing futures. | cpu core count | | `workers`* | `usize` | Number of threads to use for executing futures. | cpu core count |
| `max_blocking`* | `usize` | Limit on threads to start for blocking tasks. | `512` |
| `ident` | `string`, `false` | If and how to identify via the `Server` header. | `"Rocket"` | | `ident` | `string`, `false` | If and how to identify via the `Server` header. | `"Rocket"` |
| `keep_alive` | `u32` | Keep-alive timeout seconds; disabled when `0`. | `5` | | `keep_alive` | `u32` | Keep-alive timeout seconds; disabled when `0`. | `5` |
| `log_level` | [`LogLevel`] | Max level to log. (off/normal/debug/critical) | `normal`/`critical` | | `log_level` | [`LogLevel`] | Max level to log. (off/normal/debug/critical) | `normal`/`critical` |
@ -33,8 +34,8 @@ values:
| `ctrlc` | `bool` | Whether `ctrl-c` initiates a server shutdown. | `true` | | `ctrlc` | `bool` | Whether `ctrl-c` initiates a server shutdown. | `true` |
| `shutdown`* | [`Shutdown`] | Graceful shutdown configuration. | [`Shutdown::default()`] | | `shutdown`* | [`Shutdown`] | Graceful shutdown configuration. | [`Shutdown::default()`] |
<small>* Note: the `workers` and `shutdown.force` configuration parameters are <small>* Note: the `workers`, `max_blocking`, and `shutdown.force` configuration
only read from the [default provider](#default-provider).</small> parameters are only read from the [default provider](#default-provider).</small>
### Profiles ### Profiles
@ -138,6 +139,7 @@ sensible.
address = "127.0.0.1" address = "127.0.0.1"
port = 8000 port = 8000
workers = 16 workers = 16
max_blocking = 512
keep_alive = 5 keep_alive = 5
ident = "Rocket" ident = "Rocket"
log_level = "normal" log_level = "normal"
@ -358,6 +360,21 @@ than those provided by [`Config::figment()`]. In other words, only the values
set by the `ROCKET_WORKERS` environment variable or in the `workers` property of set by the `ROCKET_WORKERS` environment variable or in the `workers` property of
`Rocket.toml` will be considered - all other `workers` values are ignored. `Rocket.toml` will be considered - all other `workers` values are ignored.
The `max_blocking` parameter sets an upper limit on the number of threads the
underlying `async` runtime will spawn to execute potentially blocking,
synchronous tasks via [`spawn_blocking`] or equivalent. Similar to the `workers`
parameter, `max_blocking` cannot be reconfigured or be configured from sources
other than those provided by [`Config::figment()`]. Unlike `workers`, threads
corresponding to `max_blocking` are not always active and will exit if idling.
In general, the default value of `512` should not be changed unless physical or
virtual resources are scarce. Rocket only executes work on blocking threads when
required such as when performing file system I/O via [`TempFile`] or wrapping
synchronous work via [`rocket_sync_db_pools`].
[`spawn_blocking`]: @tokio/task/fn.spawn_blocking.html
[`TempFile`]: @api/rocket/fs/enum.TempFile.html
[`rocket_sync_db_pools`]: @api/rocket_sync_db_pools/index.html
## Extracting Values ## Extracting Values
Your application can extract any configuration that implements [`Deserialize`] Your application can extract any configuration that implements [`Deserialize`]