- 数据库:添加 amt_status 和 agent_status 字段 - 后端:Device 实体类和 DeviceDTO 添加新状态字段 - 后端:DeviceService 添加状态检测和更新方法 - 后端:添加 AmtStatusCheckTask 定时任务(每30秒检测一次) - 前端:设备列表页面拆分状态列显示 - 前端:统计卡片显示 AMT 和 Agent 在线/离线数量 - 网络扫描:自动设置 AMT 状态为在线 - 文档:添加 DEVICE_STATUS_SPLIT.md 和 AMT_REALTIME_STATUS.md
9.4 KiB
AMT 实时状态检测功能
功能概述
实现了 AMT 设备状态的实时检测和自动更新功能,无需手动刷新即可看到设备的在线/离线状态变化。
实现方案
后端实现
1. 定时任务 (AmtStatusCheckTask.java)
位置: backend/src/main/java/com/soybean/admin/task/AmtStatusCheckTask.java
功能:
- 每 30 秒自动检测一次所有设备的 AMT 状态
- 使用线程池并发检测,提高效率
- 只在状态变化时更新数据库,减少写入操作
- 使用 Socket 连接检测 AMT 端口(16992/16993)可用性
关键特性:
@Scheduled(fixedRate = 30000, initialDelay = 10000)
public void checkAmtStatus() {
// 每 30 秒执行一次
// 初始延迟 10 秒,等待应用完全启动
}
检测逻辑:
- 查询所有有 IP 地址的设备
- 并发检测每个设备的 AMT 端口连接性
- 先尝试 HTTP (16992),失败则尝试 HTTPS (16993)
- 根据连接结果更新设备的
amt_status字段 - 只有状态变化时才更新数据库和记录日志
线程池配置:
- 固定 20 个线程
- 使用 CompletableFuture 异步执行
- 等待所有检测完成后结束任务
2. 启用定时任务
修改: backend/src/main/java/com/soybean/admin/SoybeanAdminApplication.java
添加 @EnableScheduling 注解启用 Spring 定时任务功能:
@SpringBootApplication
@MapperScan("com.soybean.admin.mapper")
@EnableScheduling // 启用定时任务
public class SoybeanAdminApplication {
// ...
}
前端实现
1. 自动轮询刷新
位置: src/views/device/list/index.vue
功能:
- 页面加载后每 10 秒自动刷新设备列表
- 组件卸载时自动清除定时器
- 显示"自动刷新中"状态标签
实现代码:
onMounted(() => {
loadData();
// 启动定时刷新,每 10 秒刷新一次设备状态
const refreshInterval = setInterval(() => {
loadData();
}, 10000);
// 组件卸载时清除定时器
onUnmounted(() => {
clearInterval(refreshInterval);
});
});
2. 手动刷新按钮
添加了"刷新状态"按钮,用户可以随时手动刷新:
<n-button @click="handleManualRefresh" :loading="loading">
<icon-mdi-refresh class="mr-4px text-16px" />
刷新状态
</n-button>
3. 状态指示器
显示自动刷新状态:
<n-tag v-if="autoRefreshEnabled" type="success" size="small">
<icon-mdi-autorenew class="mr-4px" />
自动刷新中
</n-tag>
工作流程
完整流程图
后端定时任务 (每30秒)
↓
检测所有设备 AMT 端口
↓
更新数据库状态
↓
前端轮询 (每10秒)
↓
获取最新设备列表
↓
更新界面显示
时间线示例
T=0s: 后端启动,10秒后开始第一次检测
T=10s: 后端第一次检测所有设备
T=10s: 前端页面加载,开始第一次数据获取
T=20s: 前端第二次刷新
T=30s: 前端第三次刷新
T=40s: 后端第二次检测 + 前端第四次刷新
T=50s: 前端第五次刷新
...
性能优化
后端优化
- 并发检测: 使用 20 个线程并发检测,大幅提升检测速度
- 快速超时: Socket 连接超时设置为 3 秒,避免长时间等待
- 增量更新: 只在状态变化时更新数据库
- 简单检测: 只检测端口连接性,不进行完整的 AMT 认证
前端优化
- 合理间隔: 10 秒刷新间隔,平衡实时性和性能
- 自动清理: 组件卸载时清除定时器,避免内存泄漏
- 加载状态: 显示加载状态,提升用户体验
状态检测逻辑
检测方法
使用 TCP Socket 连接检测,而不是完整的 AMT 认证:
private boolean checkAmtConnectivity(String ipAddress) {
try {
// 尝试连接 AMT HTTP 端口
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, 16992), 3000);
socket.close();
return true;
} catch (Exception e) {
// HTTP 失败,尝试 HTTPS
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, 16993), 3000);
socket.close();
return true;
} catch (Exception ex) {
return false;
}
}
}
优点
- 快速: 不需要完整的 SOAP 请求和认证
- 轻量: 只检测端口可用性
- 可靠: 能准确判断 AMT 服务是否运行
缺点
- 不验证认证: 不检查凭证是否正确
- 端口占用: 如果端口被其他服务占用,可能误判
使用说明
1. 执行数据库更新
如果还没有执行过数据库更新,先运行:
update_device_status.bat
2. 重新编译后端
cd backend
mvn clean package -DskipTests
3. 启动后端服务
start_backend.bat
后端启动后,会在 10 秒后开始第一次 AMT 状态检测,之后每 30 秒检测一次。
4. 打开前端页面
访问设备列表页面,会看到:
- 右上角显示"自动刷新中"标签
- 设备的 AMT 状态列实时更新
- 可以点击"刷新状态"按钮手动刷新
日志查看
后端日志
查看后端控制台输出,会看到类似日志:
开始 AMT 状态检测任务
开始检测 10 个设备的 AMT 状态
设备 Server-01 (192.168.8.100) AMT 状态变化: offline -> online
设备 Server-02 (192.168.8.101) AMT 状态变化: online -> offline
AMT 状态检测任务完成
前端日志
打开浏览器开发者工具,可以看到每 10 秒发送一次设备列表请求。
测试场景
场景 1: 设备上线
- 启动一台 AMT 设备
- 等待最多 30 秒(后端检测周期)
- 前端会在下次刷新时显示设备状态变为"在线"
场景 2: 设备下线
- 关闭一台 AMT 设备
- 等待最多 30 秒(后端检测周期)
- 前端会在下次刷新时显示设备状态变为"离线"
场景 3: 手动刷新
- 点击"刷新状态"按钮
- 立即获取最新的设备状态
- 不需要等待自动刷新周期
配置参数
后端配置
在 AmtStatusCheckTask.java 中可以调整:
// 检测周期(毫秒)
@Scheduled(fixedRate = 30000, initialDelay = 10000)
// fixedRate: 30000 = 30秒
// initialDelay: 10000 = 10秒初始延迟
// 线程池大小
private final ExecutorService executorService = Executors.newFixedThreadPool(20);
// 20 个线程
// Socket 超时时间(毫秒)
socket.connect(new InetSocketAddress(ipAddress, 16992), 3000);
// 3000 = 3秒
前端配置
在 index.vue 中可以调整:
// 刷新周期(毫秒)
const refreshInterval = setInterval(() => {
loadData();
}, 10000); // 10000 = 10秒
性能影响
后端资源消耗
- CPU: 低(主要是网络 I/O 等待)
- 内存: 低(20 个线程 + 设备列表)
- 网络: 每个设备每 30 秒一次连接检测
前端资源消耗
- 网络: 每 10 秒一次 API 请求
- 内存: 低(只更新设备列表数据)
- CPU: 低(简单的数据更新和渲染)
数据库影响
- 读取: 每 30 秒读取所有设备列表
- 写入: 只在状态变化时写入(增量更新)
- 索引: 建议在
ip_address和amt_status字段上建立索引
后续优化建议
1. WebSocket 推送
替代轮询方式,使用 WebSocket 实时推送状态变化:
优点:
- 更实时
- 减少网络请求
- 降低服务器负载
实现:
- 后端使用 Spring WebSocket
- 状态变化时主动推送到前端
- 前端监听 WebSocket 消息更新界面
2. 智能检测频率
根据设备状态调整检测频率:
- 在线设备: 每 60 秒检测一次
- 离线设备: 每 30 秒检测一次
- 新添加设备: 每 10 秒检测一次(前 5 分钟)
3. 批量状态查询接口
添加专门的状态查询接口,只返回状态信息:
@GetMapping("/device/status")
public Result<Map<Long, String>> getDeviceStatus() {
// 只返回 id -> status 的映射
// 减少数据传输量
}
4. 状态变化通知
设备状态变化时发送通知:
- 邮件通知
- 短信通知
- 系统消息通知
- Webhook 回调
5. 历史状态记录
记录设备状态变化历史:
- 创建
device_status_history表 - 记录每次状态变化的时间和原因
- 生成可用性报表
故障排查
问题 1: 状态不更新
可能原因:
- 后端定时任务未启动
- 数据库连接失败
- 网络不通
排查方法:
- 查看后端日志是否有"开始 AMT 状态检测任务"
- 检查数据库
amt_status字段是否存在 - 手动测试设备网络连接
问题 2: 前端不刷新
可能原因:
- 定时器未启动
- API 请求失败
- 组件已卸载
排查方法:
- 打开浏览器开发者工具查看网络请求
- 检查控制台是否有错误
- 确认
autoRefreshEnabled为 true
问题 3: 性能问题
可能原因:
- 设备数量过多
- 检测频率过高
- 网络延迟大
解决方案:
- 增加检测周期(如改为 60 秒)
- 增加线程池大小
- 使用 WebSocket 替代轮询
总结
实现了完整的 AMT 实时状态检测功能:
✅ 后端定时任务自动检测(每 30 秒) ✅ 前端自动刷新显示(每 10 秒) ✅ 手动刷新按钮 ✅ 状态指示器 ✅ 并发检测优化 ✅ 增量数据库更新 ✅ 完整的日志记录
用户无需手动刷新,即可实时看到设备的 AMT 在线/离线状态变化。