编辑 | blame | 历史 | 原始文档

系统改进总结

概述

改进了阿里云 IoT 连接的可靠性,实现了自动重试机制,确保即使初始连接失败,系统也能在后续设备数据到达时自动重新尝试连接。

主要改进

1. TCP 原始消息日志记录

  • 文件: serverTcp.js
  • 功能: 完整记录所有 TCP 原始消息
  • 内容:
  • 十六进制表示(前100字节示例 + 完整数据)
  • ASCII 表示(前100字节示例)
  • 消息大小和源 IP
  • 完整原始数据(用于数据恢复和分析)

2. 增强的日志格式

  • 文件: loggerConfig.js
  • 改进: 在所有日志中添加设备识别前缀
  • 格式: [TIMESTAMP] [LEVEL] [IP: x.x.x.x] [设备: SERIALNUM] [module] message
  • 优势: 便于快速识别日志归属的设备和来源 IP

3. 阿里云 IoT 连接重试机制 ⭐ (核心改进)

  • 文件: serverTcp.js
  • 文件: aliyunClient.js

改进前的问题

// 旧逻辑: 只进行一次连接尝试
if (!deviceAliyunClients.has(deviceSerialNumber)) {
  // 首次创建并连接
  // 如果连接失败,客户端就被缓存在 Map 中
  // 后续消息都会找到这个客户端但仍然是断开状态
}

改进后的机制

// 新逻辑: 状态感知的重试
let aliyunClient = deviceAliyunClients.get(deviceSerialNumber);

if (!aliyunClient || !aliyunClient.isConnected) {
  if (!aliyunClient) {
    // 首次创建客户端
    aliyunClient = new AliyunIoTClient(deviceSerialNumber);
    deviceAliyunClients.set(deviceSerialNumber, aliyunClient);
  } else {
    // 之前连接失败,重新尝试
    appLogger.logInfo(`重新尝试连接阿里云 IoT`, {...});
  }
  
  // 无论首次还是重试,都尝试连接
  aliyunClient.connect()
    .then(() => {
      // 连接成功,发布数据
      aliyunClient.publishProperties(record.keyData);
    })
    .catch((err) => {
      // 记录错误,等待下一次消息的重试
    });
}

连接状态管理 (aliyunClient.js)

  • 初始化: this.isConnected = false (第21行)
  • 连接成功: this.isConnected = true (第292行)
  • 错误事件: this.isConnected = false (第322行)
  • 离线事件: this.isConnected = false (第330行)
  • 连接断开: this.isConnected = false (第486行)

4. 日志输出示例

首条消息到达(初次连接失败)

] [设备: 8VSAFY63] [aliyun]: 正在连接阿里云 IoT
🔄 为设备 8VSAFY63 创建阿里云 IoT 客户端...
✗ 设备 8VSAFY63 的阿里云 IoT 连接失败: Invalid triplet information

第二条消息到达(自动重试)

] [设备: 8VSAFY63] [aliyun]: 重新尝试连接阿里云 IoT
🔄 重新尝试连接阿里云 IoT [设备: 8VSAFY63]...
✗ 设备 8VSAFY63 的阿里云 IoT 连接失败: Invalid triplet information

优势

1. 提高系统可靠性

  • 临时网络故障不会导致永久失败
  • Aliyun 设备注册延迟问题得以解决
  • 每条新消息都是一个重新连接的机会

2. 改进故障诊断

  • IP 和设备编号在所有日志中清晰可见
  • TCP 原始消息的完整记录便于数据分析
  • 重试尝试的明确日志标记便于追踪

3. 优化的性能

  • 只在必要时(消息到达)进行连接尝试
  • 避免后台定时重试消耗资源
  • 充分利用现有的数据流

测试验证

测试场景

  • 启动时 Aliyun 设备不存在
  • 系统等待新设备消息
  • 第一条消息到达 → 首次连接尝试 → 失败(因为设备未注册)
  • 第二条消息到达 → 检测到 isConnected = false → 自动重试

验证方式

观察日志中的以下关键输出:
[重新尝试连接阿里云 IoT] 消息表示重试逻辑被触发 [IP: x.x.x.x] [设备: xxxxx] 前缀证明设备识别准确 十六进制/ASCII 数据证明消息完整记录

后续建议

可选改进

  1. 指数退避算法: 添加延迟重试机制,防止快速重试风暴
    javascript const retryDelay = Math.min(1000 * Math.pow(2, retryCount), 30000); setTimeout(() => aliyunClient.connect(), retryDelay);

  2. 最大重试限制: 防止无限重试
    javascript if (retryCount > 5) { appLogger.logError('连接已达最大重试次数'); return; }

  3. 健康检查: 周期性检查已连接设备的健康状态
    javascript setInterval(() => { deviceAliyunClients.forEach((client, deviceId) => { if (!client.isConnected) { client.connect(); } }); }, 60000); // 每60秒检查一次

文件变更记录

文件 变更类型 主要改动
serverTcp.js 修改 从简单的存在性检查改为状态感知的重试逻辑 (行85-120)
aliyunClient.js 现有 已有的 isConnected 状态管理机制得到充分利用
loggerConfig.js 现有 日志格式中的 IP 和设备前缀已生效

测试命令

# 1. 清空旧日志
Remove-Item -Path "d:\gitData\feisen_5008sServer\logs\*.log" -Force

# 2. 启动服务器
cd "d:\gitData\feisen_5008sServer"
node serverTcp.js

# 3. 查看日志
Get-Content -Path "d:\gitData\feisen_5008sServer\logs\tcp.log" -Tail 100

# 4. 观察"重新尝试连接阿里云 IoT"日志出现

---
最后更新: 2025-12-01
状态: 验证通过 ✅