admin/AMT_REALTIME_STATUS.md
lvfengfree 2e28ad1472 feat: 拆分设备状态为AMT状态和Agent状态
- 数据库:添加 amt_status 和 agent_status 字段
- 后端:Device 实体类和 DeviceDTO 添加新状态字段
- 后端:DeviceService 添加状态检测和更新方法
- 后端:添加 AmtStatusCheckTask 定时任务(每30秒检测一次)
- 前端:设备列表页面拆分状态列显示
- 前端:统计卡片显示 AMT 和 Agent 在线/离线数量
- 网络扫描:自动设置 AMT 状态为在线
- 文档:添加 DEVICE_STATUS_SPLIT.md 和 AMT_REALTIME_STATUS.md
2026-03-01 19:18:32 +08:00

9.4 KiB
Raw Blame History

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 秒,等待应用完全启动
}

检测逻辑:

  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 定时任务功能:

@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:  前端第五次刷新
...

性能优化

后端优化

  1. 并发检测: 使用 20 个线程并发检测,大幅提升检测速度
  2. 快速超时: Socket 连接超时设置为 3 秒,避免长时间等待
  3. 增量更新: 只在状态变化时更新数据库
  4. 简单检测: 只检测端口连接性,不进行完整的 AMT 认证

前端优化

  1. 合理间隔: 10 秒刷新间隔,平衡实时性和性能
  2. 自动清理: 组件卸载时清除定时器,避免内存泄漏
  3. 加载状态: 显示加载状态,提升用户体验

状态检测逻辑

检测方法

使用 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;
        }
    }
}

优点

  1. 快速: 不需要完整的 SOAP 请求和认证
  2. 轻量: 只检测端口可用性
  3. 可靠: 能准确判断 AMT 服务是否运行

缺点

  1. 不验证认证: 不检查凭证是否正确
  2. 端口占用: 如果端口被其他服务占用,可能误判

使用说明

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: 设备上线

  1. 启动一台 AMT 设备
  2. 等待最多 30 秒(后端检测周期)
  3. 前端会在下次刷新时显示设备状态变为"在线"

场景 2: 设备下线

  1. 关闭一台 AMT 设备
  2. 等待最多 30 秒(后端检测周期)
  3. 前端会在下次刷新时显示设备状态变为"离线"

场景 3: 手动刷新

  1. 点击"刷新状态"按钮
  2. 立即获取最新的设备状态
  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_addressamt_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: 状态不更新

可能原因:

  • 后端定时任务未启动
  • 数据库连接失败
  • 网络不通

排查方法:

  1. 查看后端日志是否有"开始 AMT 状态检测任务"
  2. 检查数据库 amt_status 字段是否存在
  3. 手动测试设备网络连接

问题 2: 前端不刷新

可能原因:

  • 定时器未启动
  • API 请求失败
  • 组件已卸载

排查方法:

  1. 打开浏览器开发者工具查看网络请求
  2. 检查控制台是否有错误
  3. 确认 autoRefreshEnabled 为 true

问题 3: 性能问题

可能原因:

  • 设备数量过多
  • 检测频率过高
  • 网络延迟大

解决方案:

  1. 增加检测周期(如改为 60 秒)
  2. 增加线程池大小
  3. 使用 WebSocket 替代轮询

总结

实现了完整的 AMT 实时状态检测功能:

后端定时任务自动检测(每 30 秒) 前端自动刷新显示(每 10 秒) 手动刷新按钮 状态指示器 并发检测优化 增量数据库更新 完整的日志记录

用户无需手动刷新,即可实时看到设备的 AMT 在线/离线状态变化。