目录查询是级联对接第一个要跑通的流程: 上级平台要知道下级有多少设备、编号是什么、在不在线。 一万路不可能塞进一个报文,所以必须分页——分页不省流量,省的是「单次超时的风险」。
上一节是设备说话,这一节回到平台说话。 查询是国标里最「重」的一类交互:它可能返回几万条记录。 所以它最考验「分页」和「异步」的设计。
一、四种查询各查什么
DeviceInfo 查设备本身:厂商、型号、固件版本、通道数。
调试点播前先查这个,能确认设备到底认不认这个编号。
DeviceStatus 查运行状态:是否在线、有没有录像、磁盘剩多少、告警状态。
Catalog 查目录:这是最重的一个,返回设备和通道的完整列表。
ConfigDownload 查配置:基本参数、视频参数、录像计划。
四个查询的返回量差着数量级:DeviceInfo 一个报文就够,Catalog 可能要几百页。
所以对接时先问一句「你们目录有多少条」,比什么都实在。
二、分页的两种设计
标准里给了 SumNum 字段:第一页就告诉对方总共多少条,让平台知道要翻多少页。
但「怎么翻下一页」标准没写死,常见两种做法:
一种是「带上一次的最后一条编号」,另一种是「带页码」。
第一种更可靠:目录在翻页过程中可能变化(设备上线掉线),带游标不会漏也不会重。
第二种简单,但翻页期间有增删就会错位。
这就是为什么目录同步要「可断点续传」:一万路翻两百页,中间断一次,不能从头再来。
三、为什么目录同步要异步
算一下就知道它有多慢: 每页五十条、每页一次往返,一万路要四百次往返,按五十毫秒算就是二十秒。 二十秒的操作绝不能放在注册响应里同步做, 因为注册有自己的超时,超时就重注册,重注册又触发同步,死循环。 正确做法是「先回一条「正在同步」,后台慢慢拉」,同步完再推一条「目录已更新」。 这套模式有个名字叫「最终一致」:平台不保证「此刻目录是全的」,只保证「过一会儿会全」。 接受这一点,很多设计难题就消失了。
四、动手 Demo:一万路目录,一次查不完怎么分页
先算一条设备条目多少字节,看一万路全塞一个报文会多大。 再按四种每页条数算页数、单页大小和总往返次数。
item = ("<Item><DeviceID>34020000001320000001</DeviceID>"
"<Name>北门摄像机</Name><Status>ON</Status></Item>")
print("一条", len(item), "字节")
print("一万路", "%.1f MB" % (len(item) * 10000 / 1e6))
for size in (50, 100, 500, 1000):
pages = (10000 + size - 1) // size
print(size, pages, "页",
"%.0f KB" % (len(item) * size / 1024.0),
pages * 2, "次往返")
实跑输出:
--------------------------------------------------------------------
一万路目录,一次查不完怎么分页
--------------------------------------------------------------------
**目录查询是级联对接里第一个要跑通的流程**:**上级平台要知道「下级有多少设备、编号是什么」。**
**一万路设备不可能塞进一个报文**,所以标准留了两个字段:**`SumNum` 告诉对方总共多少条**,
**`DeviceID` 用来指定从哪开始续查。**
一条设备条目 91 字节
一万路全塞一个报文 = 0.9 MB
**这个数字就是分页的理由**:**一个将近一兆的 SIP 报文,几乎必然超时或被中间设备丢掉。**
每页条数 页数 单页大小 总往返
------------------------------------------------------------------
**50 条/页** **200 页** **4 KB** **400 次往返**
**100 条/页** **100 页** **9 KB** **200 次往返**
**500 条/页** **20 页** **44 KB** **40 次往返**
**1000 条/页** **10 页** **89 KB** **20 次往返**
**第一行到第四行,页数差了二十倍**,
**但总字节数几乎一样**——**分页不省流量,省的是「单次超时的风险」。**
**每页五十条最稳,单页才几千字节,任何网络都能过。**
**代价是往返次数:一万路要四百次。**
**按每次五十毫秒算,全程二十秒。**
按每页 50 条算:400 次往返 × 50 毫秒 = 20 秒
**所以目录同步是个「慢操作」,不能放在注册响应里同步做**,**必须异步、可断点续传。**
**工程上的做法是「先返回一条「正在同步」,后台慢慢拉」。**
**`SN` 的用法要注意**:**它是消息序号,用来配对请求和响应,不是翻页游标。**
**真正的翻页靠「上一次收到的最后一条设备编号」**——**下次查询带上它,表示「从这条之后继续」。**
**这一点各厂商实现不统一,对接时务必先抓包确认。**
一条九十一字节、一万路将近一兆——这个数就是分页的理由。 一个将近一兆的 SIP 报文,几乎必然超时或被中间设备丢掉。 四行的总字节数几乎一样,页数却差二十倍:分页不省流量,它省的是「单次超时的风险」。 每页五十条最稳,单页才四 KB,任何网络都能过;代价是四百次往返、二十秒。 每页一千条只要二十次往返,但单页八十九 KB,中间任何一个环节丢一个包就得重来。 所以这个选择不是「越大越好」也不是「越小越好」,而是要跟「网络的可靠程度」匹配。 专线可以大一点,公网只能小一点。
30 秒实验
- 算一下:一万路、每页五十条,要翻多少页?(200 页)
- 想一下:为什么带游标翻页比带页码可靠?
- 想一下:为什么目录同步不能放在注册响应里做?
常见误区
- 以为「分页是为了省流量」。 总字节几乎不变,省的是单次超时风险。
- 以为「
SN是翻页游标」。 它是消息序号,翻页靠「上一次的最后一条编号」。 - 以为「目录同步可以同步做完」。 一万路要二十秒,必须异步。
自测三问(点开对答案)
1. 四种查询分别查什么? —— **`DeviceInfo` 设备信息、`DeviceStatus` 运行状态、`Catalog` 目录、`ConfigDownload` 配置**。 2. `SumNum` 字段的作用是什么? —— **在第一页就告诉对方总共多少条**,让平台知道要翻多少页。 3. 为什么带游标翻页比带页码可靠? —— **翻页期间目录可能增删**,**游标不会漏也不会重,页码会错位。**下一节讲心跳:几十字节的报文,决定平台什么时候认「它掉线了」。
- ☐ (本节完,下一节 10.08.06 状态信息报送)