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

如何在自定义tokio runtime中同时运行Rocket服务与其他任务并正常关闭

问题核心原因
  • Rocket在自定义runtime中运行时,默认仅处理自身服务的关闭逻辑,不会主动终止整个进程,你看到的Refusing to terminate runaway custom runtime提示,就是Rocket确认自身不在专属runtime中,不会干预你自定义的runtime执行流程
  • 你的主逻辑是死循环,没有监听Rocket的关闭完成事件,所以Rocket自身服务关闭后,主循环还在持续运行,导致进程无法退出
修复后的完整代码
use std::time::Instant;
use rocket::{Config, routes};
use tokio::time::{interval_at, Duration};

#[rocket::get("/ex")]
async fn test() -> &'static str {
    "OK"
}

#[tokio::main]
async fn main() {
    // 保存Rocket任务的句柄,用于监听其运行状态
    let rocket_handle = tokio::spawn(async {
        let config = Config {
            port: 8001,
            address: std::net::Ipv4Addr::new(127, 0, 0, 1).into(),
            ..Config::debug_default()
        };

        rocket::custom(&config)
            .mount("/", routes![test])
            .launch()
            .await
    });

    let start = Instant::now();
    let mut interval = interval_at(start, Duration::from_secs(5));

    loop {
        tokio::select! {
            // 监听Rocket任务退出事件,只要Rocket关闭就终止主循环
            _ = rocket_handle => {
                println!("Rocket服务已关闭,进程退出");
                break;
            }
            // 正常处理定时任务
            _ = interval.tick() => {
                println!("Other scheduled work");
            }
        }
    }
}
核心修改说明
  • 存储Rocket异步任务的JoinHandle,用来监听Rocket的运行状态
  • 用tokio::select!同时处理两类事件:只要Rocket任务执行完成(收到SIGINT后自身关闭流程走完就会结束launch()的等待),就直接终止主循环,进程就会正常退出
  • 如果需要主动触发Rocket关闭,可以在构建Rocket实例后通过shutdown()方法获取关闭触发器,在需要关闭时调用notify()方法即可主动触发Rocket的优雅关闭流程

内容的提问来源于stack exchange,提问作者jack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 05:00:01