# AMT 实时状态检测功能 ## 功能概述 实现了 AMT 设备状态的实时检测和自动更新功能,无需手动刷新即可看到设备的在线/离线状态变化。 ## 实现方案 ### 后端实现 #### 1. 定时任务 (AmtStatusCheckTask.java) **位置**: `backend/src/main/java/com/soybean/admin/task/AmtStatusCheckTask.java` **功能**: - 每 30 秒自动检测一次所有设备的 AMT 状态 - 使用线程池并发检测,提高效率 - 只在状态变化时更新数据库,减少写入操作 - 使用 Socket 连接检测 AMT 端口(16992/16993)可用性 **关键特性**: ```java @Scheduled(fixedRate = 30000, initialDelay = 10000) public void checkAmtStatus() { // 每 30 秒执行一次 // 初始延迟 10 秒,等待应用完全启动 } ``` **检测逻辑**: 1. 查询所有有 IP 地址的设备 2. 并发检测每个设备的 AMT 端口连接性 3. 先尝试 HTTP (16992),失败则尝试 HTTPS (16993) 4. 根据连接结果更新设备的 `amt_status` 字段 5. 只有状态变化时才更新数据库和记录日志 **线程池配置**: - 固定 20 个线程 - 使用 CompletableFuture 异步执行 - 等待所有检测完成后结束任务 #### 2. 启用定时任务 **修改**: `backend/src/main/java/com/soybean/admin/SoybeanAdminApplication.java` 添加 `@EnableScheduling` 注解启用 Spring 定时任务功能: ```java @SpringBootApplication @MapperScan("com.soybean.admin.mapper") @EnableScheduling // 启用定时任务 public class SoybeanAdminApplication { // ... } ``` ### 前端实现 #### 1. 自动轮询刷新 **位置**: `src/views/device/list/index.vue` **功能**: - 页面加载后每 10 秒自动刷新设备列表 - 组件卸载时自动清除定时器 - 显示"自动刷新中"状态标签 **实现代码**: ```typescript onMounted(() => { loadData(); // 启动定时刷新,每 10 秒刷新一次设备状态 const refreshInterval = setInterval(() => { loadData(); }, 10000); // 组件卸载时清除定时器 onUnmounted(() => { clearInterval(refreshInterval); }); }); ``` #### 2. 手动刷新按钮 添加了"刷新状态"按钮,用户可以随时手动刷新: ```vue 刷新状态 ``` #### 3. 状态指示器 显示自动刷新状态: ```vue 自动刷新中 ``` ## 工作流程 ### 完整流程图 ``` 后端定时任务 (每30秒) ↓ 检测所有设备 AMT 端口 ↓ 更新数据库状态 ↓ 前端轮询 (每10秒) ↓ 获取最新设备列表 ↓ 更新界面显示 ``` ### 时间线示例 ``` T=0s: 后端启动,10秒后开始第一次检测 T=10s: 后端第一次检测所有设备 T=10s: 前端页面加载,开始第一次数据获取 T=20s: 前端第二次刷新 T=30s: 前端第三次刷新 T=40s: 后端第二次检测 + 前端第四次刷新 T=50s: 前端第五次刷新 ... ``` ## 性能优化 ### 后端优化 1. **并发检测**: 使用 20 个线程并发检测,大幅提升检测速度 2. **快速超时**: Socket 连接超时设置为 3 秒,避免长时间等待 3. **增量更新**: 只在状态变化时更新数据库 4. **简单检测**: 只检测端口连接性,不进行完整的 AMT 认证 ### 前端优化 1. **合理间隔**: 10 秒刷新间隔,平衡实时性和性能 2. **自动清理**: 组件卸载时清除定时器,避免内存泄漏 3. **加载状态**: 显示加载状态,提升用户体验 ## 状态检测逻辑 ### 检测方法 使用 TCP Socket 连接检测,而不是完整的 AMT 认证: ```java 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; } } } ``` ### 优点 1. **快速**: 不需要完整的 SOAP 请求和认证 2. **轻量**: 只检测端口可用性 3. **可靠**: 能准确判断 AMT 服务是否运行 ### 缺点 1. **不验证认证**: 不检查凭证是否正确 2. **端口占用**: 如果端口被其他服务占用,可能误判 ## 使用说明 ### 1. 执行数据库更新 如果还没有执行过数据库更新,先运行: ```bash update_device_status.bat ``` ### 2. 重新编译后端 ```bash cd backend mvn clean package -DskipTests ``` ### 3. 启动后端服务 ```bash 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: 设备上线 1. 启动一台 AMT 设备 2. 等待最多 30 秒(后端检测周期) 3. 前端会在下次刷新时显示设备状态变为"在线" ### 场景 2: 设备下线 1. 关闭一台 AMT 设备 2. 等待最多 30 秒(后端检测周期) 3. 前端会在下次刷新时显示设备状态变为"离线" ### 场景 3: 手动刷新 1. 点击"刷新状态"按钮 2. 立即获取最新的设备状态 3. 不需要等待自动刷新周期 ## 配置参数 ### 后端配置 在 `AmtStatusCheckTask.java` 中可以调整: ```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` 中可以调整: ```typescript // 刷新周期(毫秒) 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. 批量状态查询接口 添加专门的状态查询接口,只返回状态信息: ```java @GetMapping("/device/status") public Result> getDeviceStatus() { // 只返回 id -> status 的映射 // 减少数据传输量 } ``` ### 4. 状态变化通知 设备状态变化时发送通知: - 邮件通知 - 短信通知 - 系统消息通知 - Webhook 回调 ### 5. 历史状态记录 记录设备状态变化历史: - 创建 `device_status_history` 表 - 记录每次状态变化的时间和原因 - 生成可用性报表 ## 故障排查 ### 问题 1: 状态不更新 **可能原因**: - 后端定时任务未启动 - 数据库连接失败 - 网络不通 **排查方法**: 1. 查看后端日志是否有"开始 AMT 状态检测任务" 2. 检查数据库 `amt_status` 字段是否存在 3. 手动测试设备网络连接 ### 问题 2: 前端不刷新 **可能原因**: - 定时器未启动 - API 请求失败 - 组件已卸载 **排查方法**: 1. 打开浏览器开发者工具查看网络请求 2. 检查控制台是否有错误 3. 确认 `autoRefreshEnabled` 为 true ### 问题 3: 性能问题 **可能原因**: - 设备数量过多 - 检测频率过高 - 网络延迟大 **解决方案**: 1. 增加检测周期(如改为 60 秒) 2. 增加线程池大小 3. 使用 WebSocket 替代轮询 ## 总结 实现了完整的 AMT 实时状态检测功能: ✅ 后端定时任务自动检测(每 30 秒) ✅ 前端自动刷新显示(每 10 秒) ✅ 手动刷新按钮 ✅ 状态指示器 ✅ 并发检测优化 ✅ 增量数据库更新 ✅ 完整的日志记录 用户无需手动刷新,即可实时看到设备的 AMT 在线/离线状态变化。