Tokio 0.2.x兼容hyper 0.12.35:如何让rt::spawn用Tokio默认执行器?
解决Tokio 0.2与Hyper 0.12执行器冲突导致的SpawnError问题
这个问题我之前也碰到过,核心原因是Hyper 0.12依赖的是futures 0.1生态的执行器体系,而你用的Tokio 0.2已经切换到了futures 0.3的runtime,两者的执行器接口不兼容,导致Hyper的rt::spawn找不到可用的执行器实例,才抛出了SpawnError { is_shutdown: true } panic。
答案是肯定的——你完全可以把Hyper rt::spawn使用的默认执行器替换成Tokio 0.2提供的那个,而且不需要修改依赖库的内部代码,具体实现步骤如下:
1. 添加兼容依赖
首先需要引入tokio-compat库,它专门用来在Tokio 0.2的runtime上运行futures 0.1的代码,包括适配执行器接口。修改你的Cargo.toml:
[dependencies] tokio = { version = "0.2.11", features = ["full"] } hyper = "0.12.35" futures = "0.1.29" tokio-compat = "0.1.6" # 适配Tokio 0.2的版本
2. 修改代码设置默认执行器
在#[tokio::main]标记的主函数中,获取当前的Tokio 0.2 runtime,然后将其包装成futures 0.1兼容的执行器,最后设置为Hyper rt模块的默认执行器:
use hyper::rt; use futures::future as future01; use tokio_compat::runtime::Compat; fn future_01() -> impl future01::Future<Item = (), Error = ()> { future01::ok(()) } #[tokio::main] async fn main() -> Result<(), std::io::Error> { // 获取当前运行的Tokio 0.2 Runtime实例 let tokio_runtime = tokio::runtime::Runtime::current().unwrap(); // 将Tokio的执行器包装成futures 0.1兼容的版本 let compat_executor = Compat::new(tokio_runtime.executor()); // 设置Hyper rt模块的默认执行器为Tokio的兼容执行器 rt::set_executor(compat_executor); // 现在调用Hyper的rt::spawn会自动使用Tokio的执行器 rt::spawn(future_01()); Ok(()) }
原理说明
tokio_compat::runtime::Compat类型实现了futures 0.1的Executortrait,它相当于一个适配器,把Tokio 0.2的执行器接口转换成futures 0.1要求的接口。- 通过
rt::set_executor设置全局默认执行器后,依赖库内部所有的rt::spawn调用都会自动使用Tokio 0.2的runtime来调度任务,完美解决执行器不兼容的问题。
内容的提问来源于stack exchange,提问作者Juan Leni
相关产品推荐
相关产品推荐

