物联网项目工作总结
这是一篇关于物联网项目的技术博客,记录了这段时间在项目环境搭建、中间件配置、功能开发等方面的工作总结。
🎵 博客音频
女声开场播报
“大家好,这是一个关于物联网项目的博客,下面的内容是这段时间工作的总结。请大家观看。”
背景音乐
🎶 物联网项目主题曲 - 科技感电子流行风格
前言
南沙物联网项目是基于 BladeX-Links 框架打造的综合性物联网平台,涵盖设备管理、数据采集、规则引擎、边缘计算等核心功能。本次工作总结从 2026年3月中旬至4月中旬,历时约一个月,主要完成了本地开发环境搭建、中间件配置排障、核心功能开发等工作。
本项目涉及的技术栈非常广泛,包括 Java/Spring Boot 后端服务、Vue3/Avue 前端框架、Nacos 配置中心与注册中心、TDengine 时序数据库、Node-RED 流程编排引擎、MySQL 关系型数据库、Redis 缓存服务等。在一个月的时间里,我们逐一攻克了环境配置、性能调优、功能实现等多方面的技术挑战,积累了丰富的物联网项目实战经验。
下面将从 环境配置、排障过程、功能开发、扩展功能 四个维度,系统性地梳理本次工作的完整过程与技术收获。
技术架构
整体架构概述
南沙物联网项目采用了经典的分层微服务架构,从下往上依次分为 数据层、服务层、网关层 和 前端层。数据层负责数据的持久化存储,服务层承载核心业务逻辑,网关层负责请求的路由与鉴权,前端层提供用户交互界面。
1 | ┌─────────────────────────────────────────────────────────────────┐ |

图1:BladeX-Links 物联网项目整体架构图
核心服务说明
| 服务名称 | 技术栈 | 端口 | 主要职责 |
|---|---|---|---|
| blade-broker | Spring Boot + MQTT | 1883 / 8888 | MQTT 消息代理,处理设备与平台的通信 |
| blade-data | Spring Boot | — | 数据采集服务,接收并处理传感器数据 |
| blade-server | Spring Boot | 80 | 核心业务服务,提供设备管理、规则配置等 API |
| blade-gateway | Spring Cloud Gateway | 8090 | API 网关,统一入口,承载鉴权与路由 |
| blade-ui | Vue3 + Avue | 5173 | 前端管理界面,用户操作入口 |
中间件选型考量
本项目在中间件选型上做了充分的技术调研与权衡:
MySQL 作为传统关系型数据库,承担结构化业务数据的存储职责,包括设备注册信息、用户账号、权限配置、规则元数据等核心业务表。MySQL 的事务特性和丰富的数据类型支持,使其成为业务数据持久化的首选。
Redis 主要用于会话缓存和热点数据加速。在物联网场景下,设备频繁上下线会产生大量状态查询请求,通过 Redis 缓存可以有效降低数据库压力,同时利用其 Pub/Sub 机制实现实时消息推送。
TDengine 是本次项目引入的时序数据库,专门针对物联网场景优化。相比通用型数据库,TDengine 在时间序列数据的写入和查询性能上有数量级的优势,同时支持数据压缩和降采样存储,大幅降低存储成本。本项目使用 TDengine 3.0.7.1 版本,通过 REST SQL 接口与业务系统对接。
MinIO 作为对象存储服务,用于存储设备采集的媒体文件(如监控图片、视频片段等)。MinIO 与 S3 兼容的 API 设计,使得后续迁移至云存储服务时无需修改业务代码。
Nacos 承担配置中心和注册中心的双重职责。所有微服务的配置文件(如数据库连接、Redis 连接、业务参数等)集中管理在 Nacos 中,服务启动时自动从 Nacos 拉取配置。同时,服务实例启动后会向 Nacos 注册自身信息,实现服务发现和负载均衡。
环境配置
Nacos 本地环境搭建
Nacos 是本项目配置管理的核心组件,其配置质量直接决定服务能否正常启动。在项目初期,我们遇到了典型的”本地环境与项目默认约定不一致”问题。
问题现象
项目启动时控制台反复出现以下错误日志:
1 | Client not connected, current status: STARTING |
服务启动后,虽然能在控制台看到部分页面,但设备注册状态始终为空,业务功能无法完整运行。
根因分析
经过深入排查,我们发现问题的根源在于多层环境偏差叠加:
第一层:默认地址不匹配
项目启动器在运行期注入 Nacos 配置,默认连接地址是 starviewnacos.com:8340,而我们最初本地运行的 Nacos 是通过 Docker 部署的,默认端口是 8848。这意味着即使本地 Nacos 能正常运行,Java 客户端也找不到正确的服务入口。
第二层:域名解析异常
starviewnacos.com 这个域名在本地解析不稳定,Java 进程有时能解析,有时解析失败并抛出 UnknownHostException。进一步检查发现,本机的代理环境变量配置导致该域名的请求被转发到了代理服务器,返回 502 错误。
第三层:namespace 不一致
早期配置全部放在 Nacos 的 public namespace 下,但项目实际读取的是 2d2e498b-060e-446f-a900-dbb840c6541b 这个特定 namespace。控制台看到配置存在,但业务服务读取不到。
第四层:gRPC 端口未开通
Nacos 2.x 版本使用 gRPC 协议进行服务注册和配置推送,主端口 8340 之外还需要开通 9340/9341 端口。我们最初只关注了主端口的连通性,忽略了 gRPC 端口的配置。
解决方案
针对上述问题,我们逐项制定解决方案:
1. 固定域名解析
在系统 hosts 文件中添加静态映射:
1 | 127.0.0.1 starviewnacos.com |
同时配置代理环境变量,排除该域名:
1 | $env:NO_PROXY = "localhost,127.0.0.1,starviewnacos.com" |
2. 使用本地解压版 Nacos
放弃 Docker 部署方式,改为使用本地解压版 Nacos 3.1。解压版 Nacos 的优势在于端口配置更灵活,不依赖 Docker 网络模式:
| 端口类型 | 端口号 | 说明 |
|---|---|---|
| API 端口 | 8340 | 主服务端口,项目默认连接此端口 |
| Console 端口 | 8380 | 控制台界面访问端口 |
| gRPC 端口 | 9340/9341 | 服务注册与配置推送端口 |
3. 对齐 namespace
在 Nacos 中创建项目指定的 namespace:
1 | Namespace ID: 2d2e498b-060e-446f-a900-dbb840c6541b |
并将 blade.yaml、blade-dev.yaml 等核心配置文件导入该 namespace。
4. 使用嵌入式存储
启动参数中添加 -DembeddedStorage=true,确保单机模式下数据存储使用嵌入式 Derby 数据库,避免外部数据库连接问题:
1 | .\startup.cmd -m standalone -DembeddedStorage=true |
最终验证
配置完成后,通过以下命令验证 Nacos 环境是否就绪:
1 | # 检查主端口 |
已确认注册成功的服务包括 cnsci-auth(认证服务)和 cnsci-desk(桌面服务),均显示 healthy=true 状态。

图2:Nacos 服务注册与配置管理流程
TDengine 时序数据库配置
TDengine 是物联网项目处理时序数据的核心组件,负责存储传感器采集的设备数据。在 TDengine 部署过程中,我们同样遇到了多个技术挑战。
版本选型历程
项目最初尝试使用 TDengine 企业版(3.3.8.8),该版本功能完整但存在两个问题:其一,企业版需要商业授权,不适合作为长期开发方案;其二,在 Windows 环境下的服务注册和开机自启配置存在兼容性问题。
经过技术调研,我们最终选择了 TDengine Server 3.0.7.1 作为主要使用版本。这是一个开源稳定版本,在功能特性和兼容性之间取得了良好平衡。
跨版本数据不兼容问题
在切换版本过程中,我们遇到了典型的高版本数据目录无法被低版本读取的问题。日志中反复出现:
1 | failed to read sdb file ... Invalid table type |
这是因为 TDengine 不同版本之间的数据文件格式存在差异,高版本创建的数据文件包含低版本无法识别的元数据结构。解决方案是清理旧数据目录,重新初始化:
1 | # 停止 TDengine 服务 |
安装目录混装问题
在排查过程中,我们还发现了一个隐蔽的安装目录混装问题。早期测试时曾在同一目录下安装过多个版本的 TDengine,导致当前运行版本的部分二进制文件和动态库是旧版本遗留的。这会造成 taosd 能正常启动,但 taosadapter 与底层通信协议不匹配的问题。
典型症状是 taosadapter 进程存在但无法连接后端 taosd,日志中持续报错 invalid packet。
正确的解决方式是执行完整的卸载清理,然后进行干净重装:
- 卸载所有旧版本 TDengine
- 删除安装目录(包括残留文件)
- 清理注册表项
- 重新执行 3.0.7.1 安装程序
项目配置对接
确认 TDengine 服务正常后,还需要修改项目的数据库连接配置。主要是将 dev 环境下的 TDengine 连接地址从远程服务器改为本地:
1 | tdengine: |
验证命令清单
以下是日常开发中常用的 TDengine 验证命令:
1 | # 检查服务状态 |
其他中间件配置
MySQL 数据库初始化
确认 MySQL 服务运行后,需要初始化项目数据库 bladex_iot。如果数据库不存在,执行以下初始化脚本:
1 | # 创建数据库 |
Redis 启动
Redis 作为缓存和会话存储服务,启动相对简单:
1 | # 方式一:使用启动脚本 |
MinIO 对象存储配置
MinIO 用于存储设备采集的媒体文件。首次启动时需要注意凭据配置必须与项目配置一致:
1 | $env:MINIO_ROOT_USER="bladexadmin" |
首次登录后需要创建名为 bladex 的存储桶,否则文件上传功能会失败。

图3:TDengine 时序数据库写入与查询流程
中间件端口总览
| 服务 | 端口 | 启动验证方式 |
|---|---|---|
| MySQL | 3306 | mysql -u root -p -e "SHOW DATABASES;" |
| Redis | 6379 | .\redis-cli.exe ping |
| TDengine REST | 6041 | curl http://127.0.0.1:6041/rest/sql -d "show databases;" |
| MinIO | 9000 | 浏览器访问 http://127.0.0.1:9000 |
| Nacos | 8340 | curl http://starviewnacos.com:8340/nacos/ |
| blade-broker | 1883/8888 | MQTT 客户端连接测试 |
| blade-server | 80 | 浏览器访问 http://localhost |
| blade-ui | 5173 | 浏览器访问 http://localhost:5173 |
排障过程
Node-RED 配置按钮 400 错误
在前端开发过程中,我们遇到了设备规则页面点击”配置”按钮后 iframe 加载 400 错误的问题。这个问题涉及前后端交互和数据关联两个层面。
问题现象
用户在 /iot/engine/device 页面点击”配置”按钮后,弹出的 iframe 无内容显示,浏览器控制台报错:
1 | GET http://localhost:1880/flows?flowId=2041793891904016385&_=1775657612771 400 (Bad Request) |
问题分析
经过代码链路追踪,我们发现问题的核心原因在于设备规则 ID 与 Node-RED Flow ID 的混淆。
前端设备规则页面点击”配置”时,拼接的 URL 是:
1 | ${website.links.edgeUrl}/#flow/${row.id}?token=${getToken()} |
这里的 row.id 是 iot_engine_device 表的主键(设备规则 ID),但 Node-RED 实际需要的是 iot_edge_flows 表的主键(Flow ID)。这是两个完全不同的概念:
| 标识 | 来源表 | 含义 |
|---|---|---|
iot_engine_device.id |
设备规则表 | 设备规则记录的唯一标识 |
iot_edge_flows.id |
流程表 | Node-RED 流程记录的唯一标识 |
Node-RED 的 getFlowById() 方法会根据传入的 flowId 去 iot_edge_flows 表查询,但当前系统中设备规则记录和 Flow 记录之间没有建立关联,导致查询返回空,进而触发 400 错误。
解决方案
针对这个问题,我们实施了”设备规则与 Flow 联动创建”的方案:
1. 数据库加字段
在 iot_engine_device 表增加 flow_id 字段,建立设备规则与 Flow 的关联:
1 | ALTER TABLE iot_engine_device |
2. 后端联动创建逻辑
在 EngineDeviceServiceImpl.submitDevice() 方法中,设备规则保存时自动创建关联的 Flow 记录:
1 | if (engineDevice.getId() == null && StringUtil.isBlank(engineDevice.getFlowId())) { |
3. 前端传参修正
修改前端代码,将 row.id 改为 row.flowId:
1 | handleFlowConfig(row) { |
同时增加空值保护,当 flowId 为空时提示用户先保存记录。
4. 删除时级联清理
设备规则删除时,同步删除关联的 Flow 记录,避免产生孤儿数据。
Node-RED 部署按钮权限问题
在修复配置按钮问题后,我们又遇到了 Node-RED 编辑器内点击”部署”按钮时返回 400 错误的问题。
问题现象
1 | POST http://localhost:1880/flows 400 (Bad Request) |
问题分析
这个错误的调用链路如下:
1 | Node-RED 编辑器前端 → POST /flows |
问题根源在于 settings.js 中的 adminAuth 配置被注释掉,导致认证策略全部失效,req.user 为 undefined。后续路由尝试访问 user.tenantId 时触发空指针异常。
解决方案
1. 恢复 adminAuth 配置
在 settings.js 中正确配置 adminAuth 和 adminToken:
1 | adminAuth: { |
2. 确保 JWT Token 有效
用户登录后获取的 JWT Token 需要能被 Node-RED 正确解析。如果使用外部鉴权系统,需要在 Node-RED 侧配置对应的 Token 验证策略。
功能开发
设备规则配置按钮实现
设备规则配置功能是本次开发的核心成果之一。该功能允许用户在设备规则列表页面直接点击”配置”按钮,通过 iframe 弹窗打开 Node-RED 流程编辑器,实现设备数据处理流程的可视化编排。
技术方案
该功能的核心实现思路是在 Avue 框架的表格操作列中新增自定义插槽,嵌入 iframe 组件加载外部流程编辑器。
1. 自定义操作列插槽
Avue 框架提供了 #menu 插槽,允许开发者自定义操作列按钮。我们在这个插槽中新增了”查看”、”配置”、”编辑”、”删除”四个按钮:
1 | <template #menu="{ row, index }"> |
2. iframe 弹窗组件
使用 Element UI 的 el-dialog 组件实现弹窗效果:
1 | <el-dialog v-model="dialogFlowVisible" title="物联感知模型设计" width="90%" top="3vh" |
关键配置说明:
destroy-on-close="true":关闭弹窗时销毁 DOM,释放 iframe 占用的内存close-on-click-modal="false":防止误触遮罩导致编辑内容丢失@closed事件:动画结束后清理 iframe src,停止后台请求
3. URL 拼接规则
配置按钮点击后,拼接的 URL 格式为:
1 | {edgeUrl}/#flow/{flowId}?token={jwtToken} |
| 组成部分 | 来源 | 说明 |
|---|---|---|
edgeUrl |
网站配置项 | 规则引擎服务地址,默认 http://localhost:1880 |
flowId |
设备规则关联的 Flow ID | 后端在创建设备规则时自动创建并关联 |
jwtToken |
用户登录态 | 用于规则引擎端的身份鉴权 |
内存管理考虑
iframe 长期驻留会占用大量浏览器内存,必须做好资源释放:
- 使用
destroy-on-close确保弹窗关闭时 DOM 被销毁 - 在
@closed回调中主动清空ruleEngineSrc,断开 iframe 的资源引用 - 对于频繁开关弹窗的场景,可以考虑增加节流保护
权限控制
配置按钮复用 engine_device_edit 权限,与编辑按钮保持一致。这是因为配置操作本质上是对规则流程的编辑行为,权限级别应该与编辑按钮相同。

图4:设备规则配置按钮 iframe 嵌入交互流程
扩展功能
Node-RED 接入 TDengine
在完成基础功能开发后,我们探索了 Node-RED 流程编辑器接入 TDengine 时序数据库的方案。这是后续实现复杂数据处理流程的基础。
技术选型
Node-RED 官方提供了 node-red-node-tdengine 插件,但该插件依赖原生的 bufferutil 和 node-gyp-build 模块,在 Windows 环境下的 Node.js 20.x 版本中安装失败。
考虑到快速验证的需求,我们采用了自建本地节点包的方案,通过 TDengine 的 REST SQL 接口进行数据读写。
实现方案
在 Node-RED 项目中新增本地节点包 node-red-contrib-tdengine:
1 | node-red-contrib-tdengine/ |
该节点包包含三个节点:
tdengine(配置节点):保存 TDengine 连接信息
| 配置项 | 默认值 | 说明 |
|---|---|---|
| host | 127.0.0.1 | TDengine 服务器地址 |
| port | 6041 | REST 服务端口 |
| database | — | 默认数据库名 |
| username | root | 用户名 |
| password | taosdata | 密码 |
tdengine in(查询节点):执行 SQL 查询并返回结果
1 | // 使用示例 |
tdengine out(写入节点):执行 INSERT/UPDATE/DELETE 等写入操作
1 | // 使用示例 |
验证测试
完成节点开发后,我们执行了完整的读写测试:
1 | # 测试连接和版本查询 |

图5:Node-RED 通过 REST SQL 接口接入 TDengine 架构
后续优化方向
当前实现是最小可用版本,后续可以进一步增强:
- 对象 Payload 转换:参考 InfluxDB 节点的用户体验,支持
msg.measurement、msg.payload格式的自动转换 - 批量写入优化:支持数组格式的批量数据写入,提高写入吞吐量
- 超级表支持:对接 TDengine 的超级表和标签功能,实现更灵活的数据模型
- 查询结果缓存:对频繁查询的数据实现本地缓存,减少数据库压力
经验总结
环境配置要点
Nacos 配置中心
- 本地 Nacos 必须对齐项目的默认地址和端口设置
- namespace 不能只看
public,业务配置通常在独立 namespace 下 - Nacos 2.x 需要同时开通 gRPC 端口(9340/9341),否则服务注册会失败
- 域名解析要稳定,建议在 hosts 文件中固定映射
- 代理环境变量要将 Nacos 域名加入白名单
TDengine 时序数据库
- 不同版本之间的数据文件不兼容,切换版本前务必清理旧数据目录
- 安装目录不能混装多个版本,二进制和动态库版本必须一致
- REST 接口(taosAdapter)是跨语言访问的最佳选择
- 确认
taosd和taosadapter两个服务都在运行
功能开发要点
前后端数据关联
- REST API 返回的数据结构要与前端期望的格式一致
- 涉及多表关联的操作,后端要做好事务控制,避免半成功状态
- 前端调用外部服务时,要做好参数校验和错误处理
iframe 嵌入交互
- 使用
destroy-on-close确保资源及时释放 - 避免在 iframe 内执行重量级操作,影响用户体验
- 考虑 iframe 与父页面的样式隔离问题
技术债务与改进方向
- Node-RED 节点包增强:当前的自建节点包功能较简单,后续可以增加更丰富的配置选项和错误处理
- 监控告警体系:目前缺乏针对中间件和业务服务的监控告警机制,需要补充
- 自动化测试:核心业务逻辑缺少单元测试和集成测试覆盖
- 文档沉淀:部分技术决策和配置细节散落在即时通讯记录中,需要系统整理
结语
本次南沙物联网项目工作历时一个月,完成了从环境搭建到功能开发的全流程工作。在这段时间里,我们成功解决了 Nacos 本地环境配置、TDengine 版本兼容、设备规则配置功能开发等多个技术挑战,积累了宝贵的物联网项目实战经验。
项目当前已经具备了完整的本地开发环境,核心功能基本跑通。后续将继续完善数据处理流程、补充监控告警体系、加强自动化测试覆盖,将项目打造成稳定可靠的物联网平台。
感谢团队成员的通力协作,使得各项工作得以顺利推进。期待在下阶段工作中,能够继续保持高效协作,共同推动项目迈向新的里程碑。
相关文档
- Nacos 本地环境与默认链路
- [TDengine 本地启动与版本兼容排障记录](./问题记录/2026-03-25 TDengine本地启动与版本兼容排障记录.md)
- [Nacos 本地链路修复记录](./问题记录/2026-03-23 Nacos本地链路修复记录.md)
- BladeX-Links 本机启动清单
- 设备规则配置按钮需求分析
- 设备规则配置按钮实现方案
- Node-RED 配置按钮与部署问题修复
- [TDengine 接入 Node-RED 方案梳理](./2026-04-13 TDengine接入Node-RED方案梳理.md)
- [Node-RED 接入 TDengine 改动总结](./环境配置/2026-04-14 Node-RED接入TDengine改动总结.md)