本文对应源码core/app/sev/vss/internal/logic/proc/fetch_data_proc.go将说明它在进程里做了哪些事、为什么要集中在一个逻辑里按时间表拉取以及典型场景ONVIF 发现、设备在线状态快照等如何体现「少请求DB/少外部依赖、多读内存」的思路。项目源码地址https://github.com/openskeye/go-vss1. 本质FetchDataLogic实现types.SipProcLogic在 VSS 启动时与其它 SIP 协程任务一起DO常驻运行。可以概括为启动阶段两条并行分支并行拉第一批数据并通过InitFetchDataState通知全进程「可调业务」。运行阶段每秒被Ticker唤醒一次按不同周期异步触发各类「刷新ServiceContext里缓存字段」的函数。也就是说它是ServiceContext——字典、平台设置、媒体节点列表、ONVIF 局域网发现结果、设备/通道在线状态快照等都尽量在这里统一更新供 HTTP / SIP / SSE / WS 等逻辑直接读内存而不是每个请求各自去 RPC 或扫库。2. 启动WaitGroup: 两个 goroutine ├── goroutine A: dictionaries() → InitFetchDataState.Done()sync.Once └── goroutine B: setting() → mediaServers() → onvifDiscover() → deviceOnlineState() → InitFetchDataState.Done()sync.Once wg.Wait() 后进入下方定时循环dictionaries()RPCConfig.DictionaryTrees写入svcCtx.DictionaryMap按字典uniqueId构建的mapsetting()RPCConfig.SettingRow经rule.NewConfig(...).Conv().Setting()与本地Config合并后写入svcCtx.Setting后序任务依赖「设置已就绪」因此放在同一分支里先于mediaServers。mediaServers()RPCConfig.MsList媒体服务器node列表写入svcCtx.MediaServerRecordsonvifDiscover()设备探测 ONVIF 设备解析 SOAP写入svcCtx.OnvifDiscoverDevices下一节将详细介绍。deviceOnlineState()RPCDevice.OnlineStateDB 聚合设备/通道online列表写入svcCtx.DeviceOnlineState*DeviceOnlineStateResp设备 map 通道 mapInitFetchDataState作为全局数据基础在入口程序中需要先行完成其它模块才能放行例如 SIPListen、SendLogic等避免启动程序错乱。3. 定时循环for v : range time.NewTicker(time.Second).C用Unix 秒做取模区分不同场景等数据获取每次触发都是异步执行不阻塞下一秒的Ticker避免某次 RPC 或 UDP 发现拖死调度。这里需要注意的是每一个携程中没有做状态处理机制如果说当前周期执行时间较长下一个n周期完成后的数据可能将会被覆盖这里可以自行优化以下。4. 典型案例ONVIF设备发现按配置Onvif.MulticastIP、WsDiscoveryPort发送固定 XMLwsDiscoveryMessageNetworkVideoTransmitter。遍历网卡JoinGroup/SetMulticastInterface提高多网卡环境下收到应答的概率。在DiscoveryTimeout内收 UDP 包解析types.OnvifWSDiscoveryResponse从Scopes/XAddrs等抽出名称、厂商、型号、IP、服务 URL 等。使用包级onvifKeyMaps对EndpointReference.Address稳定映射到本服务生成的UUID便于列表里去重与展示主键一致。最终svcCtx.OnvifDiscoverDevices records切片替换。为什么放在 FetchData 里、而不是每个 HTTP「搜索设备」再 discover 一次发现涉及组播、多网卡、超时等待、XML 解析成本高、耗时长、结果短时内相对稳定。集中每 2 分钟刷一次可再调配置前端或其它接口只读OnvifDiscoverDevices体验上是「列表可能最多延迟一个周期」但换来极快的数据响应。这与「减少对DB的频繁/重复查询」是同一思路把重 I/O / 重计算挪到后台周期任务请求路径直接读取内存数据。5. 与 DB RPC 的关系FetchDataLogic自身仍会调 RPC因此 DB 侧仍会被访问但频次被限制为周期任务且单份缓存服务多消费者设备/通道在线状态deviceOnlineState每 10 秒拉全量 map 到DeviceOnlineState。例如 SSEdevice_online_state、诊断页等若都改为只读该字段就不会每个 SSE 连接或每个 HTTP 请求都打一遍OnlineState。字典 / 设置 / 媒体服务每 4 秒刷新业务代码在热路径上读DictionaryMap、Setting、MediaServerRecords避免散落各处的「每次来一下SettingRow」。权衡优点请求延迟低、后端负载平稳、代码边界清晰获取数据优先看FetchDataLogic填充的字段。代价数据延迟TTL4s / 10s / 120*s 不等强一致场景仍需直连DB RPC读取ONVIF 列表也可能短暂滞后于真实网络。6. 小结方法主要依赖缓存位置默认刷新节奏dictionariesConfig RPCDictionaryMap启动 每 4ssettingConfig RPCSetting启动 每 4smediaServersConfig RPCMediaServerRecords启动 每 4sonvifDiscoverUDP 组播 XMLOnvifDiscoverDevices启动 每 120sdeviceOnlineStateDevice RPCDeviceOnlineState启动 每 10s7. 源码与索引fetch_data_proc本文件core/app/sev/vss/internal/logic/proc/fetch_data_proc.go初始化core/app/sev/vss/main.goInitFetchDataState.Add(2)消费DeviceOnlineState的典型逻辑core/app/sev/vss/internal/logic/sse/device_online_state.go设备/通道在线写入路径与详细解释见设备与通道在线状态.mdFetchDataLogic是VSS的统一定时数据入口——把字典、配置、媒体节点、ONVIF 发现、在线状态等按不同周期刷新进ServiceContext让业务在请求路径上多读内存、少重复访问 DB/RPC/网络ONVIF 则是其中最典型例子。
FetchDataLogic-国标视频平台信令服务器统一定时数据获源码实现
发布时间:2026/6/1 3:15:23
本文对应源码core/app/sev/vss/internal/logic/proc/fetch_data_proc.go将说明它在进程里做了哪些事、为什么要集中在一个逻辑里按时间表拉取以及典型场景ONVIF 发现、设备在线状态快照等如何体现「少请求DB/少外部依赖、多读内存」的思路。项目源码地址https://github.com/openskeye/go-vss1. 本质FetchDataLogic实现types.SipProcLogic在 VSS 启动时与其它 SIP 协程任务一起DO常驻运行。可以概括为启动阶段两条并行分支并行拉第一批数据并通过InitFetchDataState通知全进程「可调业务」。运行阶段每秒被Ticker唤醒一次按不同周期异步触发各类「刷新ServiceContext里缓存字段」的函数。也就是说它是ServiceContext——字典、平台设置、媒体节点列表、ONVIF 局域网发现结果、设备/通道在线状态快照等都尽量在这里统一更新供 HTTP / SIP / SSE / WS 等逻辑直接读内存而不是每个请求各自去 RPC 或扫库。2. 启动WaitGroup: 两个 goroutine ├── goroutine A: dictionaries() → InitFetchDataState.Done()sync.Once └── goroutine B: setting() → mediaServers() → onvifDiscover() → deviceOnlineState() → InitFetchDataState.Done()sync.Once wg.Wait() 后进入下方定时循环dictionaries()RPCConfig.DictionaryTrees写入svcCtx.DictionaryMap按字典uniqueId构建的mapsetting()RPCConfig.SettingRow经rule.NewConfig(...).Conv().Setting()与本地Config合并后写入svcCtx.Setting后序任务依赖「设置已就绪」因此放在同一分支里先于mediaServers。mediaServers()RPCConfig.MsList媒体服务器node列表写入svcCtx.MediaServerRecordsonvifDiscover()设备探测 ONVIF 设备解析 SOAP写入svcCtx.OnvifDiscoverDevices下一节将详细介绍。deviceOnlineState()RPCDevice.OnlineStateDB 聚合设备/通道online列表写入svcCtx.DeviceOnlineState*DeviceOnlineStateResp设备 map 通道 mapInitFetchDataState作为全局数据基础在入口程序中需要先行完成其它模块才能放行例如 SIPListen、SendLogic等避免启动程序错乱。3. 定时循环for v : range time.NewTicker(time.Second).C用Unix 秒做取模区分不同场景等数据获取每次触发都是异步执行不阻塞下一秒的Ticker避免某次 RPC 或 UDP 发现拖死调度。这里需要注意的是每一个携程中没有做状态处理机制如果说当前周期执行时间较长下一个n周期完成后的数据可能将会被覆盖这里可以自行优化以下。4. 典型案例ONVIF设备发现按配置Onvif.MulticastIP、WsDiscoveryPort发送固定 XMLwsDiscoveryMessageNetworkVideoTransmitter。遍历网卡JoinGroup/SetMulticastInterface提高多网卡环境下收到应答的概率。在DiscoveryTimeout内收 UDP 包解析types.OnvifWSDiscoveryResponse从Scopes/XAddrs等抽出名称、厂商、型号、IP、服务 URL 等。使用包级onvifKeyMaps对EndpointReference.Address稳定映射到本服务生成的UUID便于列表里去重与展示主键一致。最终svcCtx.OnvifDiscoverDevices records切片替换。为什么放在 FetchData 里、而不是每个 HTTP「搜索设备」再 discover 一次发现涉及组播、多网卡、超时等待、XML 解析成本高、耗时长、结果短时内相对稳定。集中每 2 分钟刷一次可再调配置前端或其它接口只读OnvifDiscoverDevices体验上是「列表可能最多延迟一个周期」但换来极快的数据响应。这与「减少对DB的频繁/重复查询」是同一思路把重 I/O / 重计算挪到后台周期任务请求路径直接读取内存数据。5. 与 DB RPC 的关系FetchDataLogic自身仍会调 RPC因此 DB 侧仍会被访问但频次被限制为周期任务且单份缓存服务多消费者设备/通道在线状态deviceOnlineState每 10 秒拉全量 map 到DeviceOnlineState。例如 SSEdevice_online_state、诊断页等若都改为只读该字段就不会每个 SSE 连接或每个 HTTP 请求都打一遍OnlineState。字典 / 设置 / 媒体服务每 4 秒刷新业务代码在热路径上读DictionaryMap、Setting、MediaServerRecords避免散落各处的「每次来一下SettingRow」。权衡优点请求延迟低、后端负载平稳、代码边界清晰获取数据优先看FetchDataLogic填充的字段。代价数据延迟TTL4s / 10s / 120*s 不等强一致场景仍需直连DB RPC读取ONVIF 列表也可能短暂滞后于真实网络。6. 小结方法主要依赖缓存位置默认刷新节奏dictionariesConfig RPCDictionaryMap启动 每 4ssettingConfig RPCSetting启动 每 4smediaServersConfig RPCMediaServerRecords启动 每 4sonvifDiscoverUDP 组播 XMLOnvifDiscoverDevices启动 每 120sdeviceOnlineStateDevice RPCDeviceOnlineState启动 每 10s7. 源码与索引fetch_data_proc本文件core/app/sev/vss/internal/logic/proc/fetch_data_proc.go初始化core/app/sev/vss/main.goInitFetchDataState.Add(2)消费DeviceOnlineState的典型逻辑core/app/sev/vss/internal/logic/sse/device_online_state.go设备/通道在线写入路径与详细解释见设备与通道在线状态.mdFetchDataLogic是VSS的统一定时数据入口——把字典、配置、媒体节点、ONVIF 发现、在线状态等按不同周期刷新进ServiceContext让业务在请求路径上多读内存、少重复访问 DB/RPC/网络ONVIF 则是其中最典型例子。