Выключение actix с более чем одной работающей системой - PullRequest
0 голосов
/ 07 февраля 2019

Мое приложение основано на библиотеке (Library-A), которая использует actix и actix-web.Я добавляю вторую библиотеку (Library-B), которая работает на http-сервере, также используя actix-web.Я использую отдельную тему и actix::system для этого.На SIGINT закрываются только системы actix Library-B, и библиотека-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?
});

Правильно ли мне запустить новую систему для независимой библиотеки?Как мне изящно выключиться?

1 Ответ

0 голосов
/ 07 февраля 2019

Вы можете поймать Ctrl+C сигнал с использованием ctrlc crate.

Использование в основном потоке можно найти в Rust-Lang-Nursery

Поскольку вы создаете свои потоки из своего основного потока и после того, как вы поймали сигнал в своем основном потоке, вы можете корректно завершить работу других потоков, наблюдая общее логическое значение в этих потоках.

В качестве дополненияесть функция stop , которая специфична для Actix.

Вы также можете использовать чан-сигнальный ящик и написать свою собственную реализацию, как ответил здесь

Чтобы создать собственную логику отключения

Проверьте логическое значение общей арки 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();
}
...