直接回答

仅在期望值与设备观测值之间可以调和的状态上使用设备影子。分别存储期望文档和上报文档,对每次变更进行版本管理,为观测附加时间戳,并暴露不确定性。不要将命令、事件历史或对离线设备的假设变成影子状态。调和必须是幂等的、有界的,并在消息延迟或乱序到达时保持安全。

范围与边界

设备影子在设备断连或响应缓慢时提供设备选定状态的平台表示。它不证明物理真实、不替代遥测历史、也不保证期望状态已被应用。影子可以说上次上报的阀门位置是关闭的;但在失联数小时后不能声称阀门当前是关闭的。

谨慎选择影子属性

当授权方可以设置目标值且设备最终能报告是否应用了该目标值时,该属性适合放入期望状态。采样间隔、显示亮度或运行模式可能适合。重启、分发、开锁或“立即运行校准”等一次性操作是带有标识符、过期和结果的命令,而非可能无限重放的持久期望值。

上报状态应包含调和所需的设备观测值,而非每个遥测采样。在可信时包含设备时间戳、平台接收时间、固件或模式版本,以及单调可比较的文档或属性版本。将历史变更保留在事件或时序存储中。

状态与版本模型

至少表示期望值和版本、上报值和版本、最后联系时间和调和状态。状态应区分待处理、已应用、已拒绝、已过期、已被替代和未知。增量是从权威文档派生的便利工具;不应成为第三个真相来源。

当服务更新期望状态时使用乐观并发。调用方提供其读取的版本,冲突更新被拒绝或通过显式领域规则合并。设备确认其处理过的期望版本。绝不能仅因上报值恰好等于期望值就推断成功;它可能是本地设置的或对应于更早的请求。

调和流程

  1. 授权服务读取当前期望版本并提交条件更新。
  2. 平台在发布通知之前持久化更新。
  3. 设备接收最新适用版本并检查兼容性、安全性和过期。
  4. 如需要则持久化意图,应用变更,然后报告处理过的期望版本和观察到的结果。
  5. 平台仅在报告满足版本和身份检查时更新调和状态。
  6. 重连时,设备和平台比较版本并选择最新的有效期望文档。
  7. 被替代或不兼容的请求保持可审计但不重放。

确定配置是作为一个文档原子化还是按属性独立版本化。原子文档简化一致性但可能导致不相关的写入者冲突。属性级更新增加合并复杂度。根据领域不变量而非框架便利性来选择。

失败模式

乱序的上报消息可能使设备看起来在回退。一个期望的重启标志可能在每次重连后永远重启。两个服务写入无版本文档可能互相静默覆盖。平台可能在设备上报后但物理执行完成前显示“已同步”。时钟偏差可能使较新的观测看起来更旧。在宽泛的 MQTT 主题上保留影子更新可能在 ACL 薄弱时跨租户泄露状态。

离线影子还诱使应用将缓存状态视为实时。每次读响应应暴露新鲜度和连接状态,使调用方能判断过期信息是否可接受。

实施清单

  • 每个影子属性都是可调和状态,而非事件或命令。
  • 期望和上报文档有显式版本。
  • 写入者使用条件更新或定义的合并规则。
  • 设备报告其实际处理过的期望版本。
  • 待处理、已应用、已拒绝、已过期、已被替代和未知可区分。
  • 影子读取附带新鲜度和最后联系上下文。
  • 重连和乱序测试证明确定性收敛。
  • 历史和审计记录位于当前状态文档之外。

评审证据

保留一个属性目录,说明负责人、类型、期望写入者、上报来源、安全影响、新鲜度预期和合并规则。对于每个新属性,演示离线更新、竞争写入者、重复通知、乱序报告、设备重启、平台恢复和不支持的期望值。保留这些测试的文档版本和决策。

审计读取影子的调用方。它们应消费新鲜度和调和状态而非仅读取缓存值。抽样生产中的冲突、长期待处理的变更、被拒绝的版本和应用前被覆盖的更新。如果运维人员经常强制设置上报值以消除差异,说明模型隐藏了工作流问题。移除未使用的属性和写入者;累积废弃状态的影子会变成一个权限不明的失控控制接口。

主要参考来源

IETF YANG-Push 规范 RFC 8641为数据存储更新、变更通知和订阅状态提供了有用的规范性概念,尽管产品影子并非 YANG 专用。MQTT 传输行为来自 OASIS MQTT 5.0 规范。产品必须记录自身的并发、持久化和调和语义。