#graceful-shutdown #shutdown #tokio #subsystem #signal #error #tasks

tokio-graceful-shutdown

用于在基于Tokio的服务中执行优雅关闭的实用工具

37个版本

0.15.1 2024年7月9日
0.15.0 2024年3月30日
0.14.3 2024年2月7日
0.14.2 2023年12月2日
0.4.1 2021年11月28日

#93 in 异步

Download history 1487/week @ 2024-05-03 1456/week @ 2024-05-10 1483/week @ 2024-05-17 1548/week @ 2024-05-24 1907/week @ 2024-05-31 2510/week @ 2024-06-07 1952/week @ 2024-06-14 1555/week @ 2024-06-21 1519/week @ 2024-06-28 1682/week @ 2024-07-05 1621/week @ 2024-07-12 1518/week @ 2024-07-19 2060/week @ 2024-07-26 1788/week @ 2024-08-02 1819/week @ 2024-08-09 1465/week @ 2024-08-16

7,489 每月下载量
用于 7 个crate(6个直接使用)

MIT/Apache

90KB
1.5K SLoC

tokio-graceful-shutdown

Crates.io Crates.io License Build Status docs.rs Coverage Status

此crate提供了用于在tokio-rs基于的服务中执行优雅关闭的实用函数。

具体来说,它提供了

  • 监听来自子系统的关闭请求
  • 从子系统手动启动关闭
  • 自动关闭
    • SIGINT/SIGTERM/Ctrl+C
    • 子系统故障
    • 子系统panic
  • 带有超时和错误传播的干净关闭流程
  • 子系统嵌套
  • 选择子系统树的局部关闭

使用示例

async fn subsys1(subsys: SubsystemHandle) -> Result<()>
{
    log::info!("Subsystem1 started.");
    subsys.on_shutdown_requested().await;
    log::info!("Subsystem1 stopped.");
    Ok(())
}

这显示了一个非常基本的异步子系统,它简单地启动,等待程序关闭被触发,然后停止自己。

现在可以像这样执行此子系统

#[tokio::main]
async fn main() -> Result<()> {
    Toplevel::new(|s| async move {
        s.start(SubsystemBuilder::new("Subsys1", subsys1))
    })
    .catch_signals()
    .handle_shutdown_requests(Duration::from_millis(1000))
    .await
    .map_err(Into::into)
}

Toplevel 对象是子系统树的根对象。然后可以使用其 SubsystemHandle 对象的 start 方法在它中启动子系统。

catch_signals 方法使 Toplevel 对象监听 SIGINT/SIGTERM/Ctrl+C 并随后启动关闭。

handle_shutdown_requestsToplevel 的最终且最重要的方法。它空闲直到程序进入关闭模式。然后,它收集所有子系统的返回值,确定全局错误状态并确保在指定的超时内完成关闭。最后,它返回一个错误值,可以直接用作 main 的返回代码。

更多示例可以在示例文件夹中查看。

构建

要在您的项目中使用此库,请进入项目目录并运行

cargo add tokio-graceful-shutdown

要运行其中一个示例(这里为01_normal_shutdown.rs),只需克隆tokio-graceful-shutdown 仓库,进入仓库文件夹并执行

cargo run --example 01_normal_shutdown

动机

在异步程序上执行优雅的关闭是一个非平凡的问题。有几种解决方案,但它们都有各自的缺点

  • 使用tokio::select进行全局取消。这是一个广泛使用的解决方案,但其缺点是取消的任务无法对其做出反应,因此它们无法优雅地关闭。

  • 使用tokio::spawn进行分叉,并通过像tokio::CancellationToken这样的机制来通知正在运行的任务需要关闭。这允许任务优雅地关闭,但需要大量的样板代码,例如

    • 将令牌传递给任务
    • 等待任务完成
    • 实现超时机制以防止挂起
    • 收集子系统返回值
    • 确保正确处理子系统错误

    如果需要进一步的功能,例如监听信号如SIGINT或SIGTERM,样板代码会变得相当混乱。

这正是这个crate旨在提供的:对所有这些样板代码的整洁抽象。

贡献

欢迎贡献!

我主要编写这个crate是为了自己的方便,因此任何改进的想法都将非常受欢迎。

依赖

~4–13MB
~129K SLoC