如何在自定义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
相关产品推荐
相关产品推荐

