You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:35:25