mirror of
https://github.com/tokio-rs/axum.git
synced 2026-09-09 00:00:12 +02:00
Notes on backpressure
This commit is contained in:
+1
-1
@@ -25,7 +25,7 @@ hyper = { version = "0.14", features = ["full"] }
|
|||||||
reqwest = { version = "0.11", features = ["json", "stream"] }
|
reqwest = { version = "0.11", features = ["json", "stream"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tokio = { version = "1.6.1", features = ["macros", "rt", "rt-multi-thread"] }
|
tokio = { version = "1.6.1", features = ["macros", "rt", "rt-multi-thread"] }
|
||||||
tower = { version = "0.4", features = ["util", "make", "timeout", "limit", "load-shed"] }
|
tower = { version = "0.4", features = ["util", "make", "timeout", "limit", "load-shed", "steer"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = "0.2"
|
tracing-subscriber = "0.2"
|
||||||
uuid = "0.8"
|
uuid = "0.8"
|
||||||
|
|||||||
@@ -24,7 +24,56 @@
|
|||||||
//! # };
|
//! # };
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! # Regarding backpressure and `Service::poll_ready`
|
||||||
|
//!
|
||||||
|
//! Generally routing to one of multiple services and backpressure doesn't mix
|
||||||
|
//! well. Ideally you would want ensure a service is ready to receive a request
|
||||||
|
//! before calling the service. However in order to know which service to call
|
||||||
|
//! you need the request...
|
||||||
|
//!
|
||||||
|
//! One approach is to not consider the router service itself ready until all
|
||||||
|
//! destination services are ready. That is the approach used by
|
||||||
|
//! [`tower::steer::Steer`].
|
||||||
|
//!
|
||||||
|
//! Another approach is to always consider all services ready (always return
|
||||||
|
//! `Poll::Ready(Ok(()))`) from `Service::poll_ready` and then actually drive
|
||||||
|
//! readiness inside the response future. This works well when your services
|
||||||
|
//! don't care about backpressure and are always ready anyway.
|
||||||
|
//!
|
||||||
|
//! tower-web expects that most services used in your app wont care about
|
||||||
|
//! backpressure and so it uses the latter strategy. However that means you
|
||||||
|
//! should avoid routing to a service (or using a middleware) that _does_ care
|
||||||
|
//! about backpressure. At the very least you should [load shed] so requests are
|
||||||
|
//! dropped quickly and don't keep piling up.
|
||||||
|
//!
|
||||||
|
//! One possible approach is to only apply backpressure sensitive middleware
|
||||||
|
//! around your entire app. This is possible because tower-web applications are
|
||||||
|
//! themselves services:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use tower_web::prelude::*;
|
||||||
|
//! use tower::ServiceBuilder;
|
||||||
|
//! # let some_backpressure_sensitive_middleware =
|
||||||
|
//! # tower::layer::util::Identity::new();
|
||||||
|
//!
|
||||||
|
//! async fn handler(request: Request<Body>) { /* ... */ }
|
||||||
|
//!
|
||||||
|
//! let app = route("/", get(handler));
|
||||||
|
//!
|
||||||
|
//! let app = ServiceBuilder::new()
|
||||||
|
//! .layer(some_backpressure_sensitive_middleware)
|
||||||
|
//! .service(app);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! However when applying middleware around your whole application in this way
|
||||||
|
//! you have to take care that errors are still being dealt with appropriately.
|
||||||
|
//!
|
||||||
|
//! Also note that handlers created from async functions don't care about
|
||||||
|
//! backpressure and are always ready. So if you're not using any Tower
|
||||||
|
//! middleware you don't have to worry about backpressure.
|
||||||
|
//!
|
||||||
//! [`Redirect`]: tower_http::services::Redirect
|
//! [`Redirect`]: tower_http::services::Redirect
|
||||||
|
//! [load shed]: tower::load_shed
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
body::{Body, BoxBody},
|
body::{Body, BoxBody},
|
||||||
|
|||||||
Reference in New Issue
Block a user