You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust多Crate依赖不同Tokio版本引发运行时错误及修复失败问题

解决Tokio版本冲突与写入InfluxDB的错误

问题根源

你遇到的there is no reactor running错误,是因为influxdb_rs crate依赖Tokio 0.1版本的runtime,而你的主程序用#[tokio::main]启动的是Tokio 1.x runtime,两者异步上下文不兼容。后续用tokio-compat修复失败,是因为没有正确处理futures版本的转换(tokio-compat针对的是futures 0.1和1.0的兼容,直接嵌套异步块会导致 trait 不匹配)。


方案一:替换为支持Tokio 1.x的InfluxDB客户端(推荐)

最稳妥的方式是弃用influxdb_rs,改用官方维护的influxdb crate(支持Tokio 1.x,API更现代)。

步骤1:更新Cargo.toml

替换原有influxdb_rs依赖:

[dependencies]
influxdb = { version = "0.7", features = ["tokio"] }
tokio = { version = "1.0", features = ["full"] }
# 其他依赖保留

步骤2:修改认证与写入代码

调整influx::authenticate()和写入逻辑,适配新crate的API:

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // ... 原有API请求代码不变 ...

    // 初始化InfluxDB客户端(替换原有的authenticate逻辑)
    let client = influxdb::Client::new(
        "http://localhost:8086", // 你的InfluxDB地址
        "your_database_name"     // 目标数据库名
    )
    .with_auth("username", "password"); // 如果需要认证

    let mut interval = interval(Duration::from_secs(300));
    loop {
        interval.tick().await; // 等待间隔,避免忙循环
        let station = api.clone().GetStation(DEVICE_ID_MAC.to_string()).await?;
        let device: Device = station.body.devices[0].to_owned();
        
        // 构造数据点
        let device_dp = influxdb::Point::new("indoor_device")
            .add_field("wifi_status", influxdb::Value::Integer(device.wifi_status))
            .add_field("co2_level", influxdb::Value::Integer(device.dashboard_data.co2))
            .add_field("humidity", influxdb::Value::Integer(device.dashboard_data.humidity))
            .add_field("noise", influxdb::Value::Integer(device.dashboard_data.noise))
            .add_field("pressure", influxdb::Value::Float(device.dashboard_data.pressure))
            .add_field("temperature", influxdb::Value::Float(device.dashboard_data.temperature))
            .add_tag("device_id", device.id) // 可选:添加标签
            .timestamp(Utc::now().timestamp());

        // 写入数据
        if let Err(e) = client.write_point(&device_dp, Some(influxdb::Precision::Seconds)).await {
            println!("写入失败: {}", e);
        }
    }
}

方案二:强行兼容Tokio 0.1(不推荐,仅当必须用influxdb_rs时)

如果你坚持使用influxdb_rs,需要正确使用tokio-compat来桥接两个版本的runtime:

步骤1:更新Cargo.toml

添加兼容依赖:

[dependencies]
influxdb_rs = "0.2"
tokio = { version = "1.0", features = ["full"] }
tokio-compat = "0.1"
futures = "0.1"

步骤2:修改客户端初始化代码

不要在Tokio 1.x runtime里嵌套新的compat runtime,而是用tokio_compat::future::Compat转换旧版futures:

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // ... 原有API请求代码不变 ...

    // 正确初始化influxdb_rs客户端:将0.1的future转换为1.x兼容的
    let client = tokio_compat::future::Compat::new(influx::authenticate()).await?;

    let mut interval = interval(Duration::from_secs(300));
    loop {
        interval.tick().await;
        let station = api.clone().GetStation(DEVICE_ID_MAC.to_string()).await?;
        let device: Device = station.body.devices[0].to_owned();
        
        let mut device_dp = point!("indoor_device")
            .add_field("wifi_status", Value::Integer(device.wifi_status))
            // ... 其他字段与原代码一致 ...
            .add_timestamp(Utc::now().timestamp());

        // 写入时同样转换future
        let write_result = tokio_compat::future::Compat::new(
            client.write_point(device_dp, Some(Precision::Minutes), None)
        ).await;

        if write_result.is_err() {
            println!("unable to write point");
        }
    }
}

关键注意点

  • 避免在Tokio 1.x runtime中手动创建新的Tokio 0.1 runtime(你的原代码错误地嵌套了runtime,导致trait不匹配)。
  • 优先选择支持Tokio 1.x的库,长期维护性更好,避免兼容带来的复杂度。

内容的提问来源于stack exchange,提问作者GrafMetrics

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 00:05:32