如何在同步函数中并发请求OpenWeatherMap API提升性能
实现同步函数内的并发API请求提升性能
核心方案
你的函数必须对外保持同步接口,但允许内部调用异步代码,我们可以借助Tokio异步运行时,在同步函数内部启动异步环境,用reqwest的异步客户端发起并发请求,替代串行请求来提升性能。
步骤与代码实现
- 添加依赖
在Cargo.toml中补充所需依赖:
[dependencies] reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1.0", features = ["rt-multi-thread"] } futures = "0.3"
- 修改后的函数代码
use std::collections::HashMap; use tokio::runtime::Runtime; use reqwest::Client; fn get_combined_data( open_weather_map_api_url: String, open_weather_map_api_key: String, coordinates: Vec<String>, metric: bool, ) -> Vec<HashMap<String, String>> { // 生成请求URL列表 let urls: Vec<String> = get_urls( open_weather_map_api_url, open_weather_map_api_key, format!( "{},{}", coordinates.get(0).expect("Improper coordinates"), coordinates.get(1).expect("Improper coordinates") ), metric, ); // 创建Tokio多线程运行时 let rt = Runtime::new().expect("Failed to create Tokio runtime"); // 在运行时中执行异步并发逻辑 rt.block_on(async { // 创建复用的异步HTTP客户端 let client = Client::new(); // 将每个URL转换为异步请求任务 let requests = urls.into_iter().map(|url| async move { client.get(url) .send() .await .expect("Url Get failed") .json::<HashMap<String, String>>() .await .expect("json expected") }); // 等待所有请求完成,统一收集结果 futures::future::join_all(requests).await }) }
关键说明
- 用
Runtime::new()创建Tokio运行时,通过block_on方法在同步函数中阻塞等待异步任务完成,既保留了函数的同步对外接口,又利用异步并发提升了请求效率。 - 复用
Client实例能避免重复创建连接,进一步优化性能。 join_all会同时触发所有请求,等待全部完成后返回结果,彻底替代原来的串行循环逻辑。- 如果需要限制并发请求数量(避免触发API限流),可以改用
tokio::task::JoinSet或第三方库(如futures-concurrency)实现批量并发控制。
内容的提问来源于stack exchange,提问作者Star
相关产品推荐
相关产品推荐

