试用安装包下载 | SMS | 在线演示
开源项目地址:https://github.com/openskeye/go-vss
背景
设备/通道上下线可能短时间爆发(网络断联、批量重启、心跳风暴)。若每次 SIP 事件都立即请求一次 DB RPC,会把 DB 连接与写入 IOPS 打满,并放大锁竞争。本仓库对在线状态变更做「先攒队列 Map,再按秒批量 flush」。
项目中的做法
1. 事件入口:SetDeviceOnlinechannel
各逻辑将DCOnlineReq写入 channel;SetDeviceOnlineStateLogic主循环读到后,以DeviceUniqueId(或通道维度)为键Set进DeviceOnlineStateUpdateMap。同一键多次翻转时,后写覆盖前写,自然合并抖动。
2. 批量 flush:proc每秒一次
proc中time.NewTicker(time.Second):
- 遍历 Map,按设备 / 通道、在线 / 离线分成四个切片;
- 分别
go setDevice(...)/go setChannel(...)做批量更新; - 最后
Clear()整个 Map,进入下一秒。
要点
- 延迟与吞吐的权衡:状态落库最坏延迟约1 秒;换得的是写合并与更低 DB QPS。对大屏「在线数」类展示通常可接受。
- 最后一次覆盖:若 1 秒内同一设备「上→下→上」,Map 中只保留最后一次,flush 时可能少一次中间态写入,这是性能优化常见取舍。
- 与 Catalog 联动:
setDevice内对下线设备会停止 Catalog定时(代码后续逻辑),避免离线设备仍被周期 Catalog。
相关代码路径
core/app/sev/vss/internal/logic/gbs_proc/set_device_online_state_loop.gocore/app/sev/vss/internal/types/types.go—SetDeviceOnline、DeviceOnlineStateUpdateMap