在多个系统运行时关闭 actix

zak*_*um1 5 rust rust-actix

我的应用程序基于使用 actix 和 actix-web 的库 (Library-A)。我正在添加第二个库(Library-B),它运行一个 http 服务器,也使用 actix-web。actix::system我为此使用了一个单独的线程。收到 SIGINT 后,仅 Library-B actix 系统关闭,而 Library-A 继续运行。后续 SIGINT 不会关闭正在运行的 actix 系统。

正常关闭两个正在运行的 actix 系统的正确方法是什么?

Library-B 的代码,用于启动新的 actix 系统并运行 http 服务器:

thread::spawn(move || {
    let sys = actix::System::new("monitor");
    server::new(|| App::new()
        .route("/metrics", http::Method::GET, endpoint))
        .bind(format!("0.0.0.0:{}", port))
        .unwrap()
        .start();
    sys.run();
    println!("Closing monitor actix system");
    // --- SIGINT gets me here... how do I shut down gracefully?
});
Run Code Online (Sandbox Code Playgroud)

我为独立图书馆启动一个新系统是否正确?如何优雅地关闭?

Web*_*rix 5

您可以Ctrl+C使用ctrlc crate 捕获信号。

主线程中的用法可以在Rust-Lang-Nursery中找到

由于您从主线程创建线程,并且在主线程中捕获信号后,您可以通过观察这些线程中的共享布尔值来优雅地关闭其他线程。

作为补充,还有Actix 特有的停止功能。

您还可以使用 chan-signal crate 并编写自定义实现,如此处回答的那样

创建您自己的关闭逻辑

检查所有线程中共享的 Arc 原子布尔值,并在主线程中更改此变量时停止执行。由于您在主线程上捕获ctrl-c信号,因此它可以通知其他参与者线程,如下所示:

use ctrlc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;

fn main() {
    let running = Arc::new(AtomicBool::new(true));
    let running2 = running.clone();
    let r = running.clone();

    let thandle = thread::spawn(move || {
        while running2.load(Ordering::Relaxed) {
            //Do your logic here
        }
        println!("Thread1 stopped.")
    });

    let thandle2 = thread::spawn(move || {
        while running.load(Ordering::Relaxed) {
            //Do your different logic here
        }
        println!("Thread2 stopped.")
    });

    ctrlc::set_handler(move || {
        r.store(false, Ordering::Relaxed);
    })
    .expect("Error setting Ctrl-C handler");

    println!("Waiting for Ctrl-C...");
    let _ = thandle.join();
    let _ = thandle2.join();
}
Run Code Online (Sandbox Code Playgroud)