刚入行不太懂。目前服务端用 springboot ,设备通讯协议是 mqtt ,然后 mqtt 服务器是用开源版的 EMQX 。然后现在有个问题,就是上一个人写的监控设备掉线是用定时任务来做的,就是隔一段时间查询数据库里的设备,哪些设备超过设定的时间没有更新状态,就认为掉线。但是这样做的问题就是隔一段时大批量更改设备状态,并且实时性不高。现在想的是哪个设备掉线了,mqtt 那边就推送这个设备掉线的信息到 java 程序中。我查了一下 mqtt 中有遗嘱功能,但是另一个技术说 EMQX 的遗嘱消息存在内存里的,进程挂了或者其他原因服务器重启了,这段时间的消息就没了,所以没用他里面的遗嘱功能。 想请教一下有这方面经验的大佬能提供一些建议。有没有别的方案可行,或者目前物联网公司的主流方案是怎么样的,谢谢
1
NessajCN 2023-12-08 15:00:21 +08:00
心跳检测呗
|
2
ymz 2023-12-08 15:06:08 +08:00
设备有心跳包,但是心跳包如果网络波动,掉线也挺频繁
而且还有设备一直在线,但是不正常上报数据,这种你算在线,离线。 |
3
superychen 2023-12-08 15:13:19 +08:00
|
4
nealHuang 2023-12-08 15:13:50 +08:00 2
遗嘱+心跳。
收到遗嘱可以认为是下线,收到心跳后,也需要做超时检查,例如 10 秒一次心跳,做一个 60s 超时,60 秒内继续收到,就继续续心跳,否则认为离线。(这块可以参考 kafka 的时间轮算法,可以管理很多实例的心跳连接,性能很高。) 至于设备一直在线、但是不上报数据,也可以利用时间轮实现,可以加多一个 异常状态 |
5
MoYi123 2023-12-08 15:23:03 +08:00
broker 都重启了, 那设备不是全部离线? 连回来的时候再慢慢更新啊.
|
7
kuanat 2023-12-08 15:54:29 +08:00
我觉得这个事情是个工程问题而非技术问题。
“监控设备掉线是用定时任务来做的”: 说明设备本身就没有心跳机制,只有数据上报功能。工程上这个数据上报行为如果是固定间隔的就能当心跳来用,如果不是,那上面的判定逻辑是没问题的。 后者情况下,不管设备是不是真下线,超过一定时间没有数据上报都认为设备已经下线。对于判定在线的设备,你也只能说截至最后一条消息的时刻,该设备还在线。再换句话,判断是否在线这个事情不需要那么准确。 “隔一段时大批量更改设备状态,并且实时性不高”: 理论上监控系统的实时性不可能强于数据上报的最小间隔,只要定时任务周期和数据上报间隔保持一致就可以了。 “mqtt 那边就推送这个设备掉线的信息到 java 程序”: 主动轮训变事件监听,很标准的做法。技术上说,数据上报消息处理流程不仅写数据库,同时转发给 java 程序让它自己维护一份在线状态表就可以了。 “EMQX 的遗嘱消息存在内存”: 这个消息丢了很重要吗,进程重启很频繁吗? 以我的经验来说,物联网业务里对于单设备状态监控的实时性和准确性要求不高的,你能根据这个数据,给出判定“设备损坏”或者“区域网络失效”之类的经验参数才是真正的目的。这个事情可以容忍非常高的 false positive ,没有必要纠结微观细节。 |
8
xwayway 2023-12-08 16:42:04 +08:00
一般都是设备发送心跳包,比如说每 5s 发送一个心跳包,你可以根据实际情况设置连续 30s 没收到心跳,就认为设备下线了。当然判定方法具体怎么做又有很多种方案了
1. 收到心跳更新一下 db ,配合定时任务,更新 db 中设备在线状态。 2. 收到心跳包更新 redis key 过期时间,同时订阅 redis key 过期事件,根据事件修改设备在线状态,或者干脆就直接从 redis 取设备在线状态,就不用更新 db 了。 具体要怎么做,还是看你实际业务。 |
9
enjoyCoding 2023-12-08 17:10:52 +08:00
之前在物联网他们就是按照上报时间大一点点判断设备是否在线的, 10 分钟上报一次数据 那他大概 12~15 分钟没上报数据我们就认为他下线了. 我当时也觉得不好
1. 因为上报数据是动作, 是否在线是状态, 由动作推理状态并不合理 2. 至少设备少上报了一条数据才会知道设备离线, 无法提前预警 但是想不出更好的办法. 嵌入式也说了 发心跳包在规模小的时候更好, 但是比较耗电, 移动物联网真的没更好办法了吧.... |
10
yazinnnn0 2023-12-08 17:29:57 +08:00
|
11
litchinn 2023-12-08 17:34:15 +08:00
不是自带吗,https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901045
emqx 像楼上说的有在线离线主题呀 |
12
youknowiam 2023-12-08 17:42:35 +08:00
不如上 ThingBoard
|
13
qinfengge 2023-12-08 17:53:00 +08:00
我今天刚写了篇博客,用的 webhook 维护的上下线通知😎
https://blog.gggg.plus/java-shi-shi-xiao-xi-tui-song--er- |
14
ChoateYao 2023-12-08 18:00:30 +08:00
这是业务问题,而不是技术问题,问你家的产品经理去。
如何定义设备掉线 |
15
andyxq 2023-12-08 19:25:18 +08:00 1
借下#8 @xwayway 的话:
一般都是设备发送心跳包,比如说每 5s 发送一个心跳包,你可以根据实际情况设置连续 30s 没收到心跳,就认为设备下线了。 一个高效一点的方案是:利用 redis 的 ZSet ,设备发送一包心跳后计算设备下次的离线时间(当前时间戳+30 秒), 写入到 ZSet 中 value 为设备 id 、score 为计算出的离线时间。(心跳计算和写入 redis 的操作要按批,不要一个一个搞) 另启动一个线程,定时每几秒试用 redis ZRANGEBYSCORE 命令获取 0 到当前时间戳的所有设备,这些设备就是要离线的设备。 然后你可以按照你的业务处理了 |
16
stinkytofu 2023-12-08 23:55:53 +08:00
楼上都没说到点子上,EMQX 系统事件中是有设备上下线的系统主题的, 你只要订阅这个主题就能收到上下线消息, 具体可以搜索一下, 使用很简单方便, 除了上下线还有其他系统事件都挺有用的
|
17
anjingdexiaocai 2023-12-09 07:57:16 +08:00 via Android
ws 连接,然后心跳检测,物联网主流是不是用 netty 呀
|
18
bthulu 2023-12-09 11:47:21 +08:00
用 zookeeper 啊, 所有设备都连到 zookeeper 上, 服务端订阅离线通知就行了
|
19
wildlife 2023-12-09 15:53:02 +08:00
设备影子
|
20
SANJI59 2023-12-11 09:37:52 +08:00
emqx 有规则规则引擎,直接 java 写个接口,配置到 emqx 规则引擎上就行。自己定义 sql 规则
|
21
yzqdm OP 感谢大家的解答,决定试试 EMQX 里面上下线主题试试
|
22
nealHuang 2023-12-11 11:47:04 +08:00
emqx 的上下线主题会导致所有设备跟 emqx 强绑定,如果哪天某一台设备连接的 mqtt broker 不是 emqx ,你这台设备就没法监测了。
|