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

如何在异步函数中调用Polars Rust API?解决Axum服务运行时错误

解决Axum中调用Polars扫描S3 Parquet文件的Runtime冲突问题

问题原因

Polars的同步scan_parquet方法在处理S3等云存储时,内部会自行启动一个异步Runtime来完成IO操作。而Axum本身运行在Tokio Runtime中,两个Runtime嵌套就会触发Cannot start a runtime from within a runtime错误。

解决办法

1. 优先使用Polars异步API

Polars提供了异步版本的扫描方法,可直接在Tokio Runtime中执行,避免内部启动新Runtime。

步骤1:启用Polars异步特性

修改Cargo.toml,确保Polars启用async及相关云存储特性:

polars = { version = "0.37.0", features = ["async", "parquet", "cloud", "aws"] }

步骤2:重构为异步函数

pub async fn lazyframe_from_s3_key(key: &str) -> Result<LazyFrame> {
    let access_key_id = std::env::var("aws_access_key_id")?;
    let secret_access_key = std::env::var("aws_secret_access_key")?;
    let region = std::env::var("aws_region")?;
    
    let cloud_options = cloud::CloudOptions::default().with_aws([
        (Key::AccessKeyId, access_key_id),
        (Key::SecretAccessKey, secret_access_key),
        (Key::Region, region),
    ]);
    
    let mut args = ScanArgsParquet::default();
    args.cloud_options = Some(cloud_options);
    
    // 使用异步扫描方法替代同步版本
    let df = LazyFrame::scan_parquet_async(key, args)
        .await?
        .with_streaming(true)
        .select([all()]);
    
    Ok(df)
}

2. 备用方案:将同步代码隔离到阻塞线程池

如果因版本限制无法使用异步API,可将同步代码放到Tokio的阻塞线程池中执行,避免Runtime嵌套:

// 在Axum Handler中调用
async fn s3_parquet_handler() -> Result<impl IntoResponse> {
    let key = "s3://your-bucket/path/to/file.parquet";
    
    // 把同步代码提交到Tokio阻塞线程池
    let df = tokio::task::spawn_blocking(move || {
        lazyframe_from_s3_key(key)
    }).await??;
    
    // 后续处理LazyFrame逻辑
    Ok(Json("处理完成"))
}

注意:此方法会占用阻塞线程,性能不如异步API,仅作为临时替代方案。

3. 版本检查

确保使用的Polars版本支持异步云存储扫描,旧版本可能缺少scan_parquet_async或相关云异步支持,建议升级到最新稳定版。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:30:02