背景:由于查询接口调用第三方平台,需要通过http请求获得设备数据,但由于第三方接口获取数据的限制,只能通过某些接口获取机柜与机房、机柜与设备关系后再查询对应设备的信息,单线程执行效果慢造成了网络io耗时较长的问题,后引入CountDownLatch计数器来解决。
接口的响应时间
使用前:
使用后:
上代码:
原来的代码(主要列出耗时代码块):
@Override
public Result searchDeviceList(HttpServletRequest httpRequest, DeviceQuery deviceQuery) {
String cookie = httpRequest.getHeader("Cookie");
List<DeviceQueryResponseVo> jsonList = new ArrayList<DeviceQueryResponseVo>();
List<CabinetVo> cabinetVoList = new ArrayList<>();
Map<String, CabinetVo> cabinetMap = new HashMap<>();
Map<String, RoomCabinet> roomCabinetMap = new HashMap<>();
Map<String, Object> result = new HashMap<>();
try {
//todo...
if (cabinetCount > 0) {
cabinetVoList = getCabinetList(cookie, CmdbConstants.CMDB_POST_CABINET_PAGE_URL, cabinetCount, cabinetVoList);
for (int i = 0; i < cabinetVoList.size(); i++) {
String cabinetId = cabinetVoList.get(i).getBkInstId();
cabinetMap.put(cabinetId, cabinetVoList.get(i));
//查询机柜-机房
List<RoomVo> cabinetRoomVoList = new ArrayList<>();
cabinetRoomVoList = geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetRoomVoList, 1, Integer.parseInt(cabinetId));
String roomId = null;
if (CollectionUtils.isNotEmpty(cabinetRoomVoList)) {
roomId = cabinetRoomVoList.get(0).getBkInstId();
}
//查询机柜-设备
List<RoomVo> cabinetDeviceVoList = new ArrayList<>();
cabinetDeviceVoList = geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetDeviceVoList, 2, Integer.parseInt(cabinetId));
for (RoomVo roomVo : cabinetDeviceVoList) {
RoomCabinet roomCabinet = new RoomCabinet();
roomCabinet.setRoomId(roomId).setCabinetId(cabinetId);
roomCabinetMap.put(roomVo.getBkAsstInstId().toString(), roomCabinet);
}
}
} else {
result.put("list", new ArrayList<DeviceQueryResponseVo>());
result.put("total", 0);
return Result.OK(result);
}
//todo...
return Result.OK(result);
} catch (InterruptedException e) {
log.error("查询线程异常 !");
return Result.error(999, "查询失败,Cookie失效!");
} catch (BaseException e) {
return Result.error(999, e.getMsg());
} catch (Exception e) {
return Result.error(999, "查询失败,Cookie失效!");
}
}
使用CountDownLatch后,查询接口部分:
@Override
public Result searchDeviceList(HttpServletRequest httpRequest, DeviceQuery deviceQuery) {
String cookie = httpRequest.getHeader("Cookie");
List<DeviceQueryResponseVo> jsonList = new ArrayList<DeviceQueryResponseVo>();
List<CabinetVo> cabinetVoList = new ArrayList<>();
Map<String, CabinetVo> cabinetMap = new HashMap<>();
Map<String, RoomCabinet> roomCabinetMap = new HashMap<>();
Map<String, Object> result = new HashMap<>();
try {
//todo...
int cabinetCount = getCount(cookie, CmdbConstants.CMDB_POST_CABINET_COUNT_URL);
CountDownLatch latch = new CountDownLatch(0);
if (cabinetCount > 0) {
cabinetVoList = getCabinetList(cookie, CmdbConstants.CMDB_POST_CABINET_PAGE_URL, cabinetCount, cabinetVoList);
latch = new CountDownLatch(cabinetVoList.size());
for (int i = 0; i < cabinetVoList.size(); i++) {
// 提交任务给线程池处理
executorConfig.asyncServiceExecutor().execute(new CabinetTask(cabinetVoList.get(i), cookie, cabinetMap, roomCabinetMap, latch,this));
}
} else {
result.put("list", new ArrayList<DeviceQueryResponseVo>());
result.put("total", 0);
return Result.OK(result);
}
// 等待所有任务完成
latch.await();
//todo...
return Result.OK(result);
} catch (InterruptedException e) {
log.error("查询线程异常 !");
return Result.error(999, "查询失败,Cookie失效!");
} catch (BaseException e) {
return Result.error(999, e.getMsg());
} catch (Exception e) {
return Result.error(999, "查询失败,Cookie失效!");
}
}
线程执行部分:
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
public class CabinetTask implements Runnable {
private DeviceServiceImpl deviceService;
private CabinetVo cabinetVo;
private String cookie;
private Map<String, CabinetVo> cabinetMap;
private Map<String, RoomCabinet> roomCabinetMap;
private CountDownLatch latch;
public CabinetTask(CabinetVo cabinetVo, String cookie, Map<String, CabinetVo> cabinetMap,
Map<String, RoomCabinet> roomCabinetMap, CountDownLatch latch, DeviceServiceImpl deviceService) {
this.cabinetVo = cabinetVo;
this.cookie = cookie;
this.cabinetMap = cabinetMap;
this.roomCabinetMap = roomCabinetMap;
this.latch = latch;
this.deviceService = deviceService;
}
@Override
public void run() {
String cabinetId = cabinetVo.getBkInstId();
cabinetMap.put(cabinetId, cabinetVo);
//查询机柜-机房
List<RoomVo> cabinetRoomVoList = new ArrayList<>();
cabinetRoomVoList = deviceService.geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, cabinetRoomVoList, 1, Integer.parseInt(cabinetId));
String roomId = null;
if (CollectionUtils.isNotEmpty(cabinetRoomVoList)) {
roomId = cabinetRoomVoList.get(0).getBkInstId();
}
//查询机柜-设备
List<RoomVo> cabinetDeviceVoList = new ArrayList<>();
cabinetDeviceVoList = deviceService.geRelationList(cookie, CmdbConstants.CMDB_POST_CABINET_DATA_CENTER_DEVICE_URL, new ArrayList<>(), 2, Integer.parseInt(cabinetVo.getBkInstId()));
// 对 cabinetDeviceVoList 进行后续处理
for (RoomVo roomVo : cabinetDeviceVoList) {
RoomCabinet roomCabinet = new RoomCabinet();
roomCabinet.setRoomId(roomId).setCabinetId(cabinetId);
roomCabinetMap.put(roomVo.getBkAsstInstId().toString(), roomCabinet);
}
// 任务完成,减少任务计数
latch.countDown();
}
}