通过CompletableFuture对上游接口进行多次调用的优化
问题描述
我在开发设备列表页面时,需要向上游平台请求设备的在线离线状态,但是上游平台只有获取单个设备点位值的接口,并没有批量获取设备点位值的接口,这就导致我需要在for循环中调用上游接口,这样导致我的接口响应时长达到了30s以上。
原有代码
public void getDeviceStatus(List<String> deviceIds) {
for (String deviceId : deviceIds) {
// 调用上游平台接口
Map<String, Integer> deviceStatusMap = queryDeviceParamValue(deviceId,"online_status");
// 后续操作省略
}
}
解决方案
- 让上游平台编写一个批量查询设备点位值的接口、
- 通过
CompletableFuture
异步多线程调用上游接口(注意:该方法要看上游平台接口能否负荷多线程的调用)
总结
方案一因为上游平台的源码并不在我们手中,等待乙方开发又太慢了,而且设备列表页设备不会超过100台,故最多同时调用100次上游平台的接口,经过测试上游平台可以承受,故采用方案二。
代码如下:
public void getDeviceStatus(List<String> deviceIds) {
// 将deviceIds转换为CompletableFuture,
// 每个 CompletableFuture 对象都会异步执行queryDeviceParamValuet方法,查询设备参在线状态
List<CompletableFuture<Map<String, Integer>>> futures = iotDeviceIds.stream()
.map(iotDeviceId -> CompletableFuture.supplyAsync(() -> {
// 调用上游平台接口
return queryDeviceParamValue(deviceId,"online_status");
}))
.collect(Collectors.toList());
// 等待所有任务完成,并获取结果
List<Map<String, Integer>> list = futures.stream().map(CompletableFuture::join)
.collect(Collectors.toList());
// 后续操作省略
}
这样我们接口的响应时长从30s降低为不到1s