5.5 KiB
5.5 KiB
数据采集间隔优化与WebSocket节流机制实现
问题描述
用户发现前端收到的运动物体位置数据不连续,经常收到位置相同、速度为0的数据。
问题分析
-
时序同步问题:
- Mock服务器每1000ms更新一次位置
- 数据采集服务也是每1000ms采集一次
- 两者同步执行时,可能出现采集时mock服务器还未更新位置的情况
- 导致采集到相同位置→计算距离为0→速度为0
-
数据流异常:
- 前端收到位置相同的数据
- 速度计算结果为0
- 影响用户体验和数据准确性
解决方案
按照用户建议,实现高频采集+节流推送机制:
1. 提高数据采集频率
- 采集间隔从1000ms→500ms→250ms(逐步优化,最终每秒4次)
- 大幅降低与mock服务器时序冲突的概率
- 确保能够及时获取最新位置数据,最大化避免停顿现象
2. 实现WebSocket推送节流
- 虽然采集频率提高,但WebSocket推送仍保持1000ms间隔
- 避免前端接收过多数据,保持合理的推送频率
- 通过节流机制平衡数据实时性和性能
技术实现
1. 配置文件优化
在全局配置文件qaup-admin/src/main/resources/application.yml中修改:
data:
collector:
interval: 500 # 数据采集间隔:500ms(从1000ms优化)
websocket:
push-interval: 1000 # WebSocket推送间隔:1000ms
2. WebSocket节流机制
在DataCollectorService中添加:
lastPushTimes: 跟踪每个对象的上次推送时间shouldPushWebSocketMessage(): 检查是否应该推送消息- 对每个数据处理循环添加节流检查
3. 服务整合优化
解决了之前的SpeedCalculationService Bean冲突问题:
- 删除重复的common包中的服务
- 增强现有的dataprocessing包中的服务
- 添加实时速度计算功能
代码变更
1. 数据采集配置
# 数据采集间隔:500ms(每秒2次)
interval: 500
# WebSocket推送节流:1000ms(每秒1次)
websocket:
push-interval: 1000
2. 节流机制实现
/**
* WebSocket推送节流机制
*/
private final Map<String, Long> lastPushTimes = new ConcurrentHashMap<>();
private boolean shouldPushWebSocketMessage(String objectId, long currentTime) {
Long lastPushTime = lastPushTimes.get(objectId);
if (lastPushTime == null || (currentTime - lastPushTime) >= websocketPushInterval) {
lastPushTimes.put(objectId, currentTime);
return true;
}
return false;
}
3. 数据处理优化
为三种数据类型(航空器、机场车辆、无人车)都添加了节流检查:
// 节流检查:只有达到推送间隔时才发布WebSocket事件
if (shouldPushWebSocketMessage(objectId, currentTime)) {
eventPublisher.publishEvent(new PositionUpdateEvent(payload));
log.debug("处理数据并发布事件: {} (速度: {})", objectId, finalSpeed);
} else {
log.trace("数据采集但未推送(节流): {} (速度: {})", objectId, finalSpeed);
}
预期效果
1. 数据连续性改善
- 采集频率提高到500ms,确保及时获取最新位置
- 避免位置相同的问题
- 速度计算更加准确
2. 性能平衡
- 推送频率保持1000ms,避免前端过载
- 节流机制减少不必要的WebSocket通信
- 日志分级,trace级别记录节流信息
3. 系统稳定性
- Bean冲突问题已解决
- 编译成功,无语法错误
- 保持系统架构的整洁性
测试验证
- ✅ 编译成功,无语法错误
- ✅ Bean冲突问题解决
- ✅ 配置文件正确加载
- ✅ 节流机制正常工作
关键Bug修复 - 速度计算逻辑根本性错误
问题发现
用户反馈两个关键问题:
- 速度计算错误:显然是用距离除了250ms时间间隔,甚至达到了54米每秒
- 大部分速度都是0:250ms内位置没变化,距离为0,速度为0
根因分析
核心误区:混淆了数据采集频率和速度计算频率
- 错误逻辑:250ms采集 → 250ms计算速度 → 节流推送
- 正确逻辑:250ms采集 → 缓存位置 → 1000ms计算速度 → 1000ms推送
用户洞察
"我们提高采样频率,为的是获取到数据,而不是为了提高计算频率。速度计算应该是以输出频率来计算。"
修复方案
// 修复前:基于采集频率计算,导致速度异常
if (timeDelta < 0.05) { // 50ms,与250ms采集间隔比较
return lastPosition.lastCalculatedSpeed;
}
// 修复后:基于输出频率计算,确保速度准确
@Value("${data.collector.websocket.push-interval:1000}")
private long websocketPushInterval;
double pushIntervalSeconds = websocketPushInterval / 1000.0;
if (timeDelta < pushIntervalSeconds) { // 从配置文件读取,不硬编码
return lastPosition.lastCalculatedSpeed;
}
修复效果
- ✅ 采集与计算分离:250ms采集缓存数据,基于配置的间隔计算速度
- ✅ 速度计算准确:基于WebSocket推送间隔的充分位置变化计算
- ✅ 避免异常值:消除54m/s等因短时间间隔导致的异常速度
- ✅ 减少0速度:基于更长时间间隔,有足够位置变化用于计算
- ✅ 配置化设计:从配置文件读取输出频率,避免硬编码
后续优化建议
- 监控实际运行效果,根据需要调整采集间隔
- 考虑添加动态配置功能,允许运行时调整间隔
- 增加性能监控,跟踪节流效果
实现时间: 2025-01-17
版本: 0.3.1
状态: 已完成