如何提升HttpClient.execute执行性能,降低批量天气接口请求耗时
性能优化方案
1. 复用HttpClient实例
现有代码最大的性能浪费是每次循环都新建
DefaultHttpClient实例,HttpClient本身是线程安全的,应该全局初始化一次复用,避免重复创建、销毁连接的无谓开销,单这一项就能减少30%以上的无效耗时。
优化后的基础代码示例:
// 全局初始化一次HttpClient,不要放在循环内部 HttpClient weatherClient = new DefaultHttpClient(); for(LatandlngList value:latandlngList) { Double lat= value.getLat(); Double lng= value.getLng(); String url = "http://api.openweathermap.org/data/2.5/weather?lat="+lat+"&lng="+lng +"&appid="+appId; HttpGet weatherReq = new HttpGet(url); HttpResponse weatherresult = weatherClient.execute(weatherReq); // 注意及时消费响应体,避免连接泄漏 EntityUtils.consume(weatherresult.getEntity()); }
2. 改串行请求为并发异步请求
原来的请求是串行执行,100次请求的总耗时是所有请求耗时的总和,改成多线程并发请求后,总耗时会降低到接近单次请求的平均耗时。建议用Java的ExecutorService线程池实现,线程数设置为10~20即可(公开API一般有请求频率限制,不要开太高避免被限流)。
示例代码:
// 初始化固定大小线程池,这里设置为10个线程 ExecutorService executor = Executors.newFixedThreadPool(10); HttpClient weatherClient = new DefaultHttpClient(); List<Future<HttpResponse>> futures = new ArrayList<>(); // 提交所有请求任务 for(LatandlngList value:latandlngList) { Future<HttpResponse> future = executor.submit(() -> { Double lat= value.getLat(); Double lng= value.getLng(); String url = "http://api.openweathermap.org/data/2.5/weather?lat="+lat+"&lng="+lng +"&appid="+appId; HttpGet weatherReq = new HttpGet(url); return weatherClient.execute(weatherReq); }); futures.add(future); } // 逐个获取结果 for(Future<HttpResponse> future : futures) { HttpResponse weatherresult = future.get(); EntityUtils.consume(weatherresult.getEntity()); // 处理响应逻辑 } // 关闭线程池 executor.shutdown();
3. 启用HTTP连接池
给HttpClient配置连接池,支持多路复用HTTP连接,进一步降低连接建立的开销:
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); // 设置最大连接数 cm.setMaxTotal(20); // 每个路由默认最大连接数 cm.setDefaultMaxPerRoute(20); HttpClient weatherClient = HttpClients.custom().setConnectionManager(cm).build();
4. 其他可优化点
- 如果OpenWeatherMap支持批量查询接口,优先用批量接口,一次请求查询多个坐标的天气,能最大幅度降低耗时
- 开启HTTP请求的GZIP压缩,减少传输数据量
- 对相同坐标的查询结果做本地缓存,避免重复请求相同坐标的接口
内容的提问来源于stack exchange,提问作者The_N
相关产品推荐
相关产品推荐

