@Async执行多线程发送请求并监听请求
场景:测试反应接口请求时比较慢,原因是因为第三方接口限制了请求时间为1天,但是接到的需要支持7天的查询。
问题:单线程 例如查询 2022-03-01 至 2022-03-07 ,
1.把时间段拆成数组["2022-03-01","2022-03-02",...."2022-03-07"]
2.使用httpclien.get("2022-03-01 00:00:00","2022-03-01 23:59:59") for循环依次查询到7号
3.合并结果集
这样执行下来2.4W个轨迹点用了2.77s
解决及优化思路: 给成多线程
1.把时间段拆成数组["2022-03-01","2022-03-02",...."2022-03-07"]
2.将每一天执行的httpclien视为一个Future,并放到数组中占位,这样可以保证数据的返回的顺序。
3. 返回值放入 Future ,合并结果集
这样执行下来2.4W个轨迹点用了1.5s
具体实现:
1.配置线程池参数 为XXXExecutor
fleet_executor:
# 核心线程数:线程池创建时候初始化的线程数
corePoolSize: 10
# 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
maxPoolSize: 20
# 缓冲队列:用来缓冲执行任务的队列
queueCapacity: 500
# 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁
keepAliveSeconds: 60
2.@Async("XXXExecutor")修饰消费类
@Slf4j @Service public class CallServiceImpl implements CallService { @Value("${fms-http.tsp.ip}") private String ipAdd; @Value("${fms-http.tsp.token}") private String token; @Value("${fms-http.tsp.http}") private String http; @Override // 指定使用beanname为callTspExecutor的线程池 @Async("FleetExecutor") public Future<String> tspByKeyAsync(String apiKey, Map<String, String> params) { String url = ApiList.getFotonAPIConfig(apiKey); String rqUrl = String.format("%s://%s%s?token=%s", http, ipAdd, url, token); try { return new AsyncResult<>(HttpClientUtils.get(rqUrl, params, null)); } catch (Exception e) { log.error(e.getMessage(), e); return new AsyncResult<>("{\"type\" : \"error\",\"success\" : \"false\",\"content\" : \"读取异常!\"}"); } } }
调用方
@Override public List<CarLineDetailVo> getTspHisLocationsV2(String vin, Date startDate, Date endDate) throws Exception { List<Future<String>> futures = Lists.newArrayList(); List<CarLineDetailVo> voList = Lists.newArrayList(); List<Pair<Date, Date>> list = DateUtils.partitionByDay(startDate, endDate, 1); for (Pair<Date, Date> pair : list) { String startTime = DateUtils.toString(pair.getKey(), DateUtils.DEFAULT_DATE_TIME_FORMAT); String endTime = DateUtils.toString(pair.getValue(), DateUtils.DEFAULT_DATE_TIME_FORMAT); futures.add(callService.tspByKeyAsync(ApiList.CAR_HIS_LOCATION_INFO, ImmutableMap.of("idCode", vin, "startDate", startTime, "endDate", endTime))); } for (Future<String> future : futures) { String jsonStr = future.get(); JSONObject rep = JSONObject.parseObject(jsonStr); try { isValid(rep); } catch (Exception e) { continue; } JSONArray arrData = rep.getJSONArray("data"); voList.addAll(arrData.toJavaList(CarLineDetailVo.class)); } return voList; }
3.合并结果(按需而定)
...