
有次客户跟我说你们这网关数据丢了半小时我当时正在吃火锅筷子差点掉锅里。之前一直觉得自己搞的IoT网关挺稳的——树莓派CM4塞进一个铝壳外挂一个RS485转接板接各种传感器上面跑着Mosquitto做MQTT Broker数据通过4G模块往云上推。看起来无懈可击对吧结果一到现场就翻车。翻车原因很简单传感器多了数据量上来了Mosquitto开始丢消息。先说说架构。这边全是Modbus RTU走RS485三十多个节点每5秒轮询一次。每个节点的数据打包成JSON通过MQTT publish到本地Broker然后网关上一个daemon进程订阅所有topic统一处理后通过4G推上云。// 传感器数据打包 cJSON *root cJSON_CreateObject(); cJSON_AddNumberToObject(root, temp, 25.6); cJSON_AddNumberToObject(root, humidity, 68.3); cJSON_AddNumberToObject(root, pressure, 1013.2); cJSON_AddItemToObject(root, ts, cJSON_CreateString(get_timestamp())); char *json_str cJSON_PrintUnformatted(root); mqtt_publish(sensor/data, json_str, QOS_1); cJSON_Delete(root); free(json_str);看着挺正常对吧问题出在QoS和Broker配置上。Mosquitto默认配置对QoS 1的消息处理其实挺佛系的。当客户端同时在线数量多、publish频率快的时候Mosquitto把消息往内存里堆堆到阈值直接drop。我之前用mosquitto -c /etc/mosquitto/mosquitto.conf启动默认max_inflight_messages是20max_queued_messages才100。三十多个节点每5秒发一次网关自己的daemon还要往云端发一份队列根本不够用。改了一轮配置max_inflight_messages 100 max_queued_messages 1000 persistence true persistence_location /var/lib/mosquitto/改了之后好了一点但偶尔还是丢。后来查文档才发现Mosquitto在订阅端处理速度跟不上发布端的时候即使改了队列大小也会因为消息过期时间到了而丢弃。subscription的QoS如果设成0那随缘收消息吧。我最后换了EMQX。说实话一开始觉得杀鸡用牛刀但用上就真香了。EMQX自带Dashboard能直观看到有多少消息in/out、哪个topic堆积了、客户端连接状态一目了然。而且它的共享订阅机制特别适合多节点网关场景——多个网关实例组集群分摊消息不存在单点瓶颈。安装倒是不复杂wget https://www.emqx.io/downloads/broker/v5.0.0/emqx-5.0.0-ubuntu20.04-amd64.deb sudo dpkg -i emqx-5.0.0-*.deb sudo systemctl start emqx默认端口1883Dashboard在18083。我最喜欢的是规则引擎直接在页面上写SQL-like规则把特定topic的数据转发到其他Broker或HTTP服务省掉了自己写转发daemon的活SELECT payload.temp, payload.humidity, payload.ts FROM sensor/# WHERE payload.temp 40 OR payload.humidity 90 DO mqtt:publish({topicalarm/high, qos1})这一下子解决了我之前转发daemon的性能瓶颈。原来自己写的Python转发脚本处理大量消息时GIL锁就是硬伤。用EMQX规则引擎直接在Broker层面搞定延迟从几百ms降到几十ms。折腾了三个周末才把方案稳定下来。现在的结构是传感器 → RS485 → 网关EMQX 边缘计算 → 4G → 云MQTT → 后端。中间加了一层边缘过滤只有超阈值的数据实时上云正常数据每分钟批量上报省了不少流量费。最讽刺的是什么最开始选Mosquitto就是觉得它轻量、配置简单。结果越用越发现简单的东西在小规模没问题规模一起来全是坑。别问我怎么知道的。