MST

星途 面试题库

面试题:Rust中reqwest库API调用的性能优化与并发控制

假设有一组API地址列表,需要使用reqwest库并发调用这些API,并在所有调用完成后汇总结果。同时,要对并发数量进行控制(例如最多并发5个请求)以避免资源耗尽。请设计并实现一个Rust程序,详细说明如何优化性能,包括如何处理异步任务、错误处理以及资源管理等方面。
50.2万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
use reqwest;
use futures::future::{join_all, BoxFuture};
use std::sync::Arc;
use std::time::Duration;

async fn fetch_api(url: &str) -> Result<String, reqwest::Error> {
    let client = reqwest::Client::new();
    client.get(url)
        .timeout(Duration::from_secs(10))
        .send()
        .await?
        .text()
        .await
}

async fn run_api_calls(api_urls: &[&str]) -> Result<Vec<String>, reqwest::Error> {
    let semaphore = Arc::new(tokio::sync::Semaphore::new(5));
    let mut tasks = Vec::new();

    for url in api_urls {
        let semaphore = semaphore.clone();
        tasks.push(tokio::spawn(async move {
            let permit = semaphore.acquire().await.expect("Failed to acquire permit");
            let result = fetch_api(url).await;
            drop(permit);
            result
        }));
    }

    let results = join_all(tasks).await;
    let mut final_results = Vec::new();
    for result in results {
        final_results.push(result??);
    }
    Ok(final_results)
}

#[tokio::main]
async fn main() {
    let api_urls = &["http://example.com/api1", "http://example.com/api2", "http://example.com/api3"];
    match run_api_calls(api_urls).await {
        Ok(results) => println!("Results: {:?}", results),
        Err(e) => eprintln!("Error: {}", e),
    }
}

性能优化

  1. 异步任务处理
    • 使用tokio::spawn将每个API调用包装成独立的异步任务。
    • 使用futures::future::join_all等待所有任务完成,这可以高效地管理多个异步任务,不会阻塞主线程。
  2. 错误处理
    • fetch_api函数中,使用?操作符处理reqwest::Error,将错误向上传递。
    • run_api_calls函数中,对每个任务的结果进行?操作,收集所有成功的结果,若有任何一个任务失败则整个操作失败。
  3. 资源管理
    • 使用tokio::sync::Semaphore控制并发数量,确保同时最多有5个请求在执行,避免资源耗尽。
    • fetch_api函数中,设置reqwest::Client的超时时间,防止请求长时间挂起占用资源。

通过以上方式,程序能够高效地并发调用多个API,同时合理管理资源和处理错误。