将axum Server放入tokio::spawn后无法并行处理请求求助
Axum服务器并行处理请求问题排查
代码文件
src/server.rs
// src/server.rs use axum::{ extract::Path, response::{IntoResponse, Response}, routing::get, }; pub struct Server {} impl Server { pub async fn run() -> Result<(), Box<dyn std::error::Error>> { let axum_http_make_service = axum::Router::new() .route("/:sec", get(wait_sec_event)) .into_make_service(); let http_server = axum::Server::bind(&"0.0.0.0:4000".parse().unwrap()).serve(axum_http_make_service); let http_handle = tokio::spawn(http_server); let _ = tokio::try_join!(http_handle)?; Ok(()) } } async fn wait_sec_event(Path(sec): Path<String>) -> Response { let a = std::time::Duration::from_secs(sec.parse::<u64>().unwrap()); std::thread::sleep(a); "yo".into_response() }
src/app.rs
// src/app.rs use std::net::SocketAddr; use crate::server; pub struct App { port: SocketAddr, } impl App { pub fn new(p: SocketAddr) -> Self { Self { port: p } } pub async fn run(self) -> Result<(), Box<dyn std::error::Error>> { server::Server::run().await } }
src/main.rs
// src/main.rs use std::net::SocketAddr; use app::App; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // build our application with a single route let app = App::new(SocketAddr::from(([0, 0, 0, 0], 4000))); app.run().await } pub mod app; pub mod server;
问题
我在实现Axum服务器时发现,若将axum::Server::bind(&"0.0.0.0:4000".parse().unwrap()).serve(axum_http_make_service)放入tokio::spawn中而非直接使用await.unwrap(),服务器将无法并行处理请求。例如先执行curl 127.0.0.1:4000/10,再执行curl 127.0.0.1:4000/3,第二个请求需等待第一个完成后才会执行;但直接使用await则不会出现此问题。请问我可能哪里出错了?
原因及解决方法
问题核心不在tokio::spawn,而是你在请求处理函数wait_sec_event里用了阻塞式的std::thread::sleep,而非Tokio提供的异步睡眠tokio::time::sleep。
std::thread::sleep会直接阻塞当前线程,Tokio调度器无法在这段时间内将线程分配给其他请求处理任务。当服务器通过tokio::spawn启动时,请求处理的线程调度逻辑变化,阻塞操作的影响被放大,导致请求串行执行。- 换成
tokio::time::sleep(a).await后,异步睡眠会主动让出线程控制权,Tokio调度器可以在这段空闲时间处理其他请求,从而实现并行处理。
修改后的wait_sec_event函数:
async fn wait_sec_event(Path(sec): Path<String>) -> Response { let a = std::time::Duration::from_secs(sec.parse::<u64>().unwrap()); tokio::time::sleep(a).await; // 替换为Tokio的异步睡眠 "yo".into_response() }
补充说明:不管服务器是直接await还是用tokio::spawn启动,只要处理函数存在阻塞操作,都会影响并行性能。Axum是异步框架,所有耗时操作都应使用异步版本,避免阻塞执行线程。
内容的提问来源于stack exchange,提问作者ron
相关产品推荐
相关产品推荐

