注意:Tokio 网站在graceful shutdown 上有一个页面。
如果您要杀死多个任务,则应使用broadcast channel 发送关闭消息。可以和tokio::select!一起使用。
use tokio::sync::broadcast::Receiver;
// You may want to log errors rather than return them in this function.
pub async fn start(kill: Receiver<()>) -> Result<(), std::io::Error> {
tokio::select! {
output = real_start() => output,
_ = kill.recv() => Err(...),
}
}
pub async fn real_start() -> Result<(), std::io::Error> {
loop {
let mut data = vec![0; 1024];
socket.recv_from(&mut data).await?;
}
}
然后要杀死所有任务,在频道上发送消息。
要只杀死单个任务,可以使用JoinHandle::abort 方法,它会尽快杀死任务。请注意,此方法仅在 Tokio 1.x 和 0.3.x 中可用,要使用 Tokio 0.2.x 中止任务,请参阅下面的下一节。
let task = tokio::spawn(start());
...
task.abort();
作为JoinHandle::abort 的替代品,您可以使用期货箱中的abortable。生成任务时,请执行以下操作:
let (task, handle) = abortable(start());
tokio::spawn(task);
然后你可以通过调用abort 方法终止任务。
handle.abort();
当然,带有select! 的频道也可以用于杀死单个任务,可能与oneshot 频道而不是广播频道结合使用。
所有这些方法都保证real_start 方法在.await 处被终止。在两个.awaits 之间运行代码时,无法终止该任务。你可以阅读更多关于为什么这是here。
mini-redis 项目包含一个可访问的服务器正常关闭的真实示例。此外,Tokio 教程有关于 select 和 channels 的章节。