如何高效的判断设备是否离线?

手无护鸡之力 2023-10-18 14:06:48

用心跳包机制维护设备状态,如何高效的判断设备是否离线?记录最新心跳包时间,定时循环一遍判断时间差是否超时?这种好像有低效。有什么好的方法吗?

...全文
245 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
CSDN-Ada助手 2023-10-18
精选
  • 打赏
  • 举报
回复
您的问题已经帮您同步至问答, 链接: https://ask.csdn.net/questions/8014063, 请您保持关注, 如果回答有帮助解决此问题, 麻烦您动动小手给相关的回答点赞, Ada会在评论区为您更新结题状态
水の尽头 2024-07-30
  • 打赏
  • 举报
回复

优化方法:
使用优先队列(最小堆)
将设备的心跳包时间戳存储在一个最小堆中,堆顶的元素总是最早的时间戳。通过这个结构,每次心跳包到达更新时间戳时,只需要调整对应设备的位置。

在定时器中,只要检查堆顶的元素是否超时即可,避免了遍历整个设备列表。

基于事件驱动
结合事件通知机制,可以在设备报告心跳包时触发事件。每个设备心跳包的时间差通过定时器回调单独处理,而不是统一遍历所有设备。

高效利用事件循环机制(如Node.js中的事件驱动或者Python中的异步IO),在心跳包超时后马上触发超时处理。

哈希表加定时检查

将设备的心跳时间戳存储在哈希表或字典中,定时任务只检查当前时间点需要检验的部分设备,而不是全部(例如每次只检查一个固定数量的设备,按时间分区)。

这种方法通过分阶段进行检查,避免一次性所有设备的全量遍历。

示例代码(基于Python,使用优先队列)

import heapq
import time

class DeviceMonitor:
def init(self, timeout):
self.timeout = timeout
self.device_heap = []
self.device_map = {}

def update_heartbeat(self, device_id):
    current_time = time.time()
    if device_id in self.device_map:
        self.device_map[device_id][1] = current_time
    else:
        entry = [current_time, device_id]
        self.device_map[device_id] = entry
        heapq.heappush(self.device_heap, entry)

def check_timeouts(self):
    current_time = time.time()
    while self.device_heap and self.device_heap[0][0] + self.timeout < current_time:
        oldest = heapq.heappop(self.device_heap)
        del self.device_map[oldest[1]]
        print(f"Device {oldest[1]} is offline")

使用示例:

monitor = DeviceMonitor(timeout=30)

模拟心跳更新

monitor.update_heartbeat("deviceA")
time.sleep(10)
monitor.update_heartbeat("deviceB")

定时检查

time.sleep(35)
monitor.check_timeouts() # 输出:Device deviceA is offline
import heapq
import time

class DeviceMonitor:
def init(self, timeout):
self.timeout = timeout
self.device_heap = []
self.device_map = {}

def update_heartbeat(self, device_id):
    current_time = time.time()
    if device_id in self.device_map:
        self.device_map[device_id][1] = current_time
    else:
        entry = [current_time, device_id]
        self.device_map[device_id] = entry
        heapq.heappush(self.device_heap, entry)

def check_timeouts(self):
    current_time = time.time()
    while self.device_heap and self.device_heap[0][0] + self.timeout < current_time:
        oldest = heapq.heappop(self.device_heap)
        del self.device_map[oldest[1]]
        print(f"Device {oldest[1]} is offline")

使用示例:

monitor = DeviceMonitor(timeout=30)

模拟心跳更新

monitor.update_heartbeat("deviceA")
time.sleep(10)
monitor.update_heartbeat("deviceB")

定时检查

time.sleep(35)
monitor.check_timeouts() # 输出:Device deviceA is offline
这种方式使得检查心跳包超时的操作变得更高效,减轻了性能问题。

手无护鸡之力 2024-08-07
  • 举报
回复
@水の尽头 差不多是这意思,我用了LRU缓存机制实现的
  • 打赏
  • 举报
回复

这就像你在地面,同伴下了深井中的迷宫,俩人都没动,你拉着绳子一头,他牵着另一头,那么怎么知道他还牵着绳子没有呢?毕竟,他把绳子丢地上了,你还是看到绳子垂在井里,那就时不时拽两下试试手感,还要告诉他要是自己主动丢掉的时候先拽两下让你知道。但绳子要是自己断了,还是得自己拽两下才知道。要么就一直拽紧,一断就知道。再不行就安排个能飞的东西盯着绳子每个摩擦的拐角,一个拐角一个,一看到绳子段了就拽靠近你的那端,但是数量要多少是不知道的。那么除非你和他哪天发明了更牛p的连接着的东西,否则目前的办法也就那样吧

ZGQ_一地夏天 2023-10-18
  • 打赏
  • 举报
回复

以TCP协议说明下。如果关闭应用APP,系统底层有文件描述符回收机制,如果关闭的是连接的socket套接字文件描述符,会通知对端套接字关闭并走TCP的四步放手流程,这些底层都会处理好。如果是断网或者机器宕机等问题,是可以通过心跳包让服务端感知客户端用户是否还在线,这种方法必定会有一定延迟。而且心跳的间隔和缺失多少次则判断用户离线这些参数需要综合考虑,多大会导致判断离线不精准,过小的话如果服务端负载过高时会误判用户离线(服务端对请求处理不过来,无法处理一些用户的心跳,则会导致这些用户被判断为离线)。

37,743

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • WuKongSecurity@BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧