如何优雅地关闭 Tokio 运行时以响应 SIGTERM?
How do I gracefully shutdown the Tokio runtime in response to a SIGTERM?
我有一个 main
函数,我在其中创建了 Tokio 运行time 和 运行 两个期货。
use tokio;
fn main() {
let mut runtime = tokio::runtime::Runtime::new().unwrap();
runtime.spawn(MyMegaFutureNumberOne {});
runtime.spawn(MyMegaFutureNumberTwo {});
// Some code to 'join' them after receiving an OS signal
}
如何接收 SIGTERM
,等待所有未完成的任务(NotReady
s)并退出应用程序?
处理信号很棘手,解释如何处理所有可能的情况过于宽泛。信号的实现不是跨平台标准的,所以我的回答是针对 Linux 的。如果想更跨平台,使用POSIX函数sigaction
结合pause
;这将为您提供更多控制权。
实现您想要的效果的一种方法是使用 tokio_signal crate to catch signals, like this: (doc example)
extern crate futures;
extern crate tokio;
extern crate tokio_signal;
use futures::prelude::*;
use futures::Stream;
use std::time::{Duration, Instant};
use tokio_signal::unix::{Signal, SIGINT, SIGTERM};
fn main() -> Result<(), Box<::std::error::Error>> {
let mut runtime = tokio::runtime::Runtime::new()?;
let sigint = Signal::new(SIGINT).flatten_stream();
let sigterm = Signal::new(SIGTERM).flatten_stream();
let stream = sigint.select(sigterm);
let deadline = tokio::timer::Delay::new(Instant::now() + Duration::from_secs(5))
.map(|()| println!("5 seconds are over"))
.map_err(|e| eprintln!("Failed to wait: {}", e));
runtime.spawn(deadline);
let (item, _rest) = runtime
.block_on_all(stream.into_future())
.map_err(|_| "failed to wait for signals")?;
let item = item.ok_or("received no signal")?;
if item == SIGINT {
println!("received SIGINT");
} else {
assert_eq!(item, SIGTERM);
println!("received SIGTERM");
}
Ok(())
}
该程序将等待所有当前任务完成并捕获选定的信号。这似乎不适用于 Windows,因为它会立即关闭程序。
另一个答案是针对 Tokio 版本 0.1.x,它非常旧。对于 Tokio 版本 1.x.y,官方 Tokio 教程有一个关于此主题的页面:Graceful shutdown
我有一个 main
函数,我在其中创建了 Tokio 运行time 和 运行 两个期货。
use tokio;
fn main() {
let mut runtime = tokio::runtime::Runtime::new().unwrap();
runtime.spawn(MyMegaFutureNumberOne {});
runtime.spawn(MyMegaFutureNumberTwo {});
// Some code to 'join' them after receiving an OS signal
}
如何接收 SIGTERM
,等待所有未完成的任务(NotReady
s)并退出应用程序?
处理信号很棘手,解释如何处理所有可能的情况过于宽泛。信号的实现不是跨平台标准的,所以我的回答是针对 Linux 的。如果想更跨平台,使用POSIX函数sigaction
结合pause
;这将为您提供更多控制权。
实现您想要的效果的一种方法是使用 tokio_signal crate to catch signals, like this: (doc example)
extern crate futures;
extern crate tokio;
extern crate tokio_signal;
use futures::prelude::*;
use futures::Stream;
use std::time::{Duration, Instant};
use tokio_signal::unix::{Signal, SIGINT, SIGTERM};
fn main() -> Result<(), Box<::std::error::Error>> {
let mut runtime = tokio::runtime::Runtime::new()?;
let sigint = Signal::new(SIGINT).flatten_stream();
let sigterm = Signal::new(SIGTERM).flatten_stream();
let stream = sigint.select(sigterm);
let deadline = tokio::timer::Delay::new(Instant::now() + Duration::from_secs(5))
.map(|()| println!("5 seconds are over"))
.map_err(|e| eprintln!("Failed to wait: {}", e));
runtime.spawn(deadline);
let (item, _rest) = runtime
.block_on_all(stream.into_future())
.map_err(|_| "failed to wait for signals")?;
let item = item.ok_or("received no signal")?;
if item == SIGINT {
println!("received SIGINT");
} else {
assert_eq!(item, SIGTERM);
println!("received SIGTERM");
}
Ok(())
}
该程序将等待所有当前任务完成并捕获选定的信号。这似乎不适用于 Windows,因为它会立即关闭程序。
另一个答案是针对 Tokio 版本 0.1.x,它非常旧。对于 Tokio 版本 1.x.y,官方 Tokio 教程有一个关于此主题的页面:Graceful shutdown