优雅地处理 SIGTERM (Ctrl-c) 并关闭线程池

问题描述 投票:0回答:1

目前,我正在阅读 Rust 书的最后一章,实现 HTTP 服务器的优雅关闭。

现在我想稍微扩展一下逻辑,并在按 Ctrl+C 后触发正常关闭。因此我使用 ctrlc crate

但是由于各种借用检查器错误,我无法使其工作:

fn main() {
    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
    let pool = ThreadPool::new(4);

    ctrlc::set_handler(|| {
        // dropping will trigger ThreadPool::drop and gracefully shutdown the running workers
        drop(pool); // compile error, variable is moved here
    })
    .unwrap();

    for stream in listener.incoming() {
        let stream = stream.unwrap();

        pool.execute(|| {
            handle_connection(stream);
        });
    }
}

我尝试了使用 Arc<> 和附加 mpsc 通道的多种方法,但没有成功。

为了使其发挥作用,最佳实践是什么?

rust concurrency
1个回答
0
投票

我最终得到:

fn main() {
    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
    let pool = ThreadPool::new(4);

    let (tx, rx) = channel();

    ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel."))
        .expect("Error setting Ctrl-C handler");

    for stream in listener.incoming() {
        let stream = stream.unwrap();

        pool.execute(|| {
            handle_connection(stream);
        });

        match rx.try_recv() {
            Ok(_) => break,
            Err(_) => continue,
        }
    }
}

但它有一个缺陷。即按下 Ctrl+C 后,关闭过程不会立即触发,而是在收到另一个请求后才触发。然后循环将中断,ThreadPool 超出范围并被丢弃,从而触发正常关闭逻辑。

该解决方案足以满足我的学习目的。在生产环境中,人们将依赖于像 actix

这样的 Web 框架的正常关闭
© www.soinside.com 2019 - 2024. All rights reserved.