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

@ -17,24 +17,25 @@ is configured with. This means that no matter which configuration provider
Rocket is asked to use, it must be able to read the following configuration 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 |
| `ident` | `string`, `false` | If and how to identify via the `Server` header. | `"Rocket"` | | `max_blocking`* | `usize` | Limit on threads to start for blocking tasks. | `512` |
| `keep_alive` | `u32` | Keep-alive timeout seconds; disabled when `0`. | `5` | | `ident` | `string`, `false` | If and how to identify via the `Server` header. | `"Rocket"` |
| `log_level` | [`LogLevel`] | Max level to log. (off/normal/debug/critical) | `normal`/`critical` | | `keep_alive` | `u32` | Keep-alive timeout seconds; disabled when `0`. | `5` |
| `cli_colors` | `bool` | Whether to use colors and emoji when logging. | `true` | | `log_level` | [`LogLevel`] | Max level to log. (off/normal/debug/critical) | `normal`/`critical` |
| `secret_key` | [`SecretKey`] | Secret key for signing and encrypting values. | `None` | | `cli_colors` | `bool` | Whether to use colors and emoji when logging. | `true` |
| `tls` | [`TlsConfig`] | TLS configuration, if any. | `None` | | `secret_key` | [`SecretKey`] | Secret key for signing and encrypting values. | `None` |
| `limits` | [`Limits`] | Streaming read size limits. | [`Limits::default()`] | | `tls` | [`TlsConfig`] | TLS configuration, if any. | `None` |
| `limits.$name` | `&str`/`uint` | Read limit for `$name`. | form = "32KiB" | | `limits` | [`Limits`] | Streaming read size limits. | [`Limits::default()`] |
| `ctrlc` | `bool` | Whether `ctrl-c` initiates a server shutdown. | `true` | | `limits.$name` | `&str`/`uint` | Read limit for `$name`. | form = "32KiB" |
| `shutdown`* | [`Shutdown`] | Graceful shutdown configuration. | [`Shutdown::default()`] | | `ctrlc` | `bool` | Whether `ctrl-c` initiates a server shutdown. | `true` |
| `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`]