最近两年在工业自动化领域做了几个物联网项目,发现很多企业都在面临设备上云的转型需求。传统SCADA系统虽然稳定,但扩展性和数据分析能力已经跟不上数字化工厂的要求。基于这个痛点,我选择用若依(Ruoyi)这个成熟框架作为基础,开发了一套轻量级物联网平台。
选择若依框架主要看中它三个特点:一是自带完善的权限管理和工作流引擎,省去了重复造轮子的时间;二是前后端分离架构方便定制化开发;三是社区活跃度高,遇到问题容易找到解决方案。这套物联网平台目前已经稳定运行在三个工厂的产线监控场景,日均处理设备数据超过200万条。
平台采用经典的四层架构:
特别说明下协议选择策略:MQTT用于高频传感器数据(采样间隔<5s),Modbus TCP对接传统PLC设备,HTTP协议则留给边缘计算节点上报聚合数据。这种混合协议设计在实际项目中非常实用,能覆盖90%以上的工业场景。
数据库方面采用时序数据库+关系型数据库双写模式:
消息中间件对比了RabbitMQ和EMQX后,最终选择EMQX 5.0作为MQTT broker。实测数据显示,在500个设备并发连接时,EMQX的资源占用比RabbitMQ低40%左右,而且自带规则引擎可以做一些简单的数据预处理。
传统物联网平台通常需要手动录入设备信息,我们开发了一套动态注册机制:
java复制// 设备首次连接时的处理逻辑
public Device registerDevice(String deviceKey, String protocol) {
Device device = deviceMapper.selectByKey(deviceKey);
if (device == null) {
device = new Device();
device.setDeviceKey(deviceKey);
device.setProtocolType(protocol);
device.setStatus(0); // 未激活状态
deviceMapper.insert(device);
// 发送待审核通知
sysNoticeService.sendNotice("新设备待审核", deviceKey);
}
return device;
}
这套机制配合若依的审批流功能,设备管理员在后台就能完成设备入网审核,大大减少了运维工作量。
针对高频设备数据写入,我们做了三项优化:
实测数据显示,在阿里云4核8G的ECS上,这套方案可以稳定支持每秒8000条数据的写入。这里有个重要经验:InfluxDB的batch_size参数需要根据设备数量动态调整,我们的经验公式是:
code复制batch_size = max(100, 设备数量 × 0.2)
基于若依的工作流引擎扩展了设备告警功能,支持四种触发条件:
告警规则的DSL设计示例:
json复制{
"ruleType": "threshold",
"deviceId": "temp_sensor_01",
"field": "temperature",
"operator": ">",
"value": 85,
"severity": "urgent",
"notify": ["sms", "email"]
}
利用EMQX的SQL规则引擎实现简单的流处理:
sql复制SELECT
payload.temp as temperature,
payload.hum as humidity,
clientid as device_id
FROM
"sensor/data"
WHERE
payload.temp > 80 OR payload.hum > 90
这种在消息层就完成的数据过滤,可以减少30%以上的无效数据传输。
基于ECharts开发了设备状态矩阵视图,关键技术点:
javascript复制// 状态颜色计算算法
function getStatusColor(value, min, max) {
const ratio = (value - min) / (max - min);
const hue = ((1 - ratio) * 120).toString(10);
return `hsl(${hue}, 100%, 50%)`;
}
针对历史数据查询慢的问题,我们实现了三级缓存策略:
配合时间分片加载技术,即使查询30天的数据,响应时间也能控制在2秒以内。
使用Docker Compose编排关键服务:
yaml复制version: '3'
services:
emqx:
image: emqx:5.0
ports:
- "1883:1883"
- "8083:8083"
influxdb:
image: influxdb:2.0
volumes:
- ./influxdb:/var/lib/influxdb2
redis:
image: redis:7.0-alpine
生产环境建议将每个服务部署在独立节点上,特别是InfluxDB要保证足够的IOPS。
我们重点监控四个核心指标:
在Grafana中配置的告警阈值:
时区问题:InfluxDB默认使用UTC时间,前端显示时需要做时区转换。我们的解决方案是在写入数据时加上时区标记:
java复制Point.point("measurement")
.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.addTag("timezone", "Asia/Shanghai")
设备重连风暴:某次网络波动导致500台设备同时重连,把服务打挂。后来我们实现了指数退避重连机制:
c复制// 设备端重连算法
int reconnect_delay = min(1000 * pow(2, retry_count), 30000);
大屏内存泄漏:长时间运行的数据看板会出现内存增长。通过Chrome Performance工具分析发现是ECharts实例未及时销毁。解决方案是在Vue的beforeUnmount钩子中手动清理:
javascript复制beforeUnmount() {
this.chart.dispose();
this.chart = null;
}
这套基于若依的物联网平台经过半年多的迭代,已经形成了相对完整的解决方案。最大的体会是:在物联网项目中,稳定性比功能丰富更重要。下一步计划整合边缘计算能力,把部分计算逻辑下沉到网关设备,进一步降低云端压力。