@Async執行多執行緒傳送請求並監聽請求
阿新 • • 發佈:2022-03-08
場景:測試反應介面請求時比較慢,原因是因為第三方介面限制了請求時間為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.合併結果(按需而定)
...