你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

如何了解和使用 Device Update for IoT Hub 中的增量更新(预览)

通过使用增量更新功能,可以生成一个小型更新,它仅表示两个完整更新(源映像和目标映像)之间的更改。 此方法非常适合用于减少将更新下载到设备的带宽,尤其是在源更新和目标更新之间只有少量更改的情况下。

注意

增量更新功能目前处于公共预览阶段。

使用 Device Update for IoT Hub 增量更新的要求

  • 源和目标更新文件必须是 SWUpdate (SWU) 格式。
  • 在每个 SWUpdate 文件中,必须有一个使用 Ext2、Ext3 或 Ext4 文件系统的原始映像。 可以使用 gzip 或 zstd 压缩该映像。
  • 增量生成过程使用 zstd 压缩重新压缩目标 SWU 更新,以达到最佳增量。 将此重新压缩的目标 SWU 更新与生成的增量更新文件一起导入到设备更新服务。
  • 在设备上的 SWUpdate 中,还必须启用 zstd 解压缩。

配置带有设备更新代理和增量处理器组件的设备

为了使设备能够从设备更新服务下载和安装增量更新,需要具有多个组件并完成相应配置。

设备更新代理

设备更新代理协调设备上的更新过程,包括下载、安装和重启操作。 将设备更新代理添加到设备中,并对其进行配置以供使用。 使用代理版本 1.0 或更高版本。 有关说明,请参阅设备更新代理预配

更新处理程序

更新处理程序与设备更新代理集成以执行实际的更新安装。 对于增量更新,如果还没有要修改的 SWUpdate 更新处理程序,请从microsoft/swupdate:2 更新处理程序开始。 如果使用自己的更新处理程序,请确保在 SWUpdate 中启用 zstd 解压缩

增量处理器

下载差异文件后,增量处理器会在设备上重新创建原始 SWU 映像文件,以便更新处理程序可以安装 SWU 文件。 在 Azure/iot-hub-device-update-delta GitHub 存储库中可以找到增量处理器代码。

若要将增量处理器组件添加到设备映像并对其进行配置以供使用,请按照 README.md 说明使用 CMAKE 从源生成增量处理器。 在那里,通过将共享对象 (libadudiffapi.so) 复制到 /usr/lib 目录来直接安装它:

sudo cp <path to libadudiffapi.so> /usr/lib/libadudiffapi.so
sudo ldconfig

将源 SWU 映像文件添加到设备

将增量更新下载到设备后,必须将其与以前缓存在设备上的有效源 SWU 文件进行比较。 增量更新需要此过程才能重新创建完整的目标映像。 填充此缓存映像的最简单方法是通过设备更新服务将完整的映像更新部署到设备(使用现有导入部署过程)。 只要设备已配置设备更新代理(版本 1.0 或更高版本)和增量处理器,设备更新代理就会自动缓存已安装的 SWU 文件,以供以后增量更新使用。

如果想要直接在设备上预填充源映像,则映像的预期路径为:

[BASE_SOURCE_DOWNLOAD_CACHE_PATH]/sha256-[ENCODED HASH]

默认情况下,BASE_SOURCE_DOWNLOAD_CACHE_PATH 是路径 /var/lib/adu/sdc/[provider][provider] 值是源 SWU 文件的 updateId 的 Provider 部分。

ENCODED_HASH 是二进制的 SHA256 的 base64 十六进制字符串,但在对 base64 十六进制字符串进行编码后,它会对字符进行如下编码:

  • + 编码为 octets _2B
  • / 编码为 octets _2F
  • = 编码为 octets _3D

使用 DiffGen 工具生成增量更新

环境先决条件

在使用 DiffGen 创建增量之前,需要在环境计算机上下载和/或安装一些内容。 建议使用 Linux 环境,特别是 Ubuntu 20.04(如果以本机方式在 Windows 上运行,则建议使用适用于 Linux 的 Windows 子系统)。

下表提供了所需内容的列表、检索位置以及建议的安装(如有必要):

二进制名称 获取位置 如何安装
DiffGen Azure/iot-hub-device-update-delta GitHub 存储库 从根文件夹中,选择 Microsoft.Azure.DeviceUpdate.Diffs.[version].nupkg 文件。 详细了解 NuGet 包
.NETCore 运行时,版本 6.0.0 通过终端/包管理器 适用于 Linux 的说明。 只需要运行时。

依赖项

zstd_compression_tool 用于解压缩存档的映像文件,并使用 zstd 重新压缩它们。 此过程可确保用于生成差异的所有存档文件与存档中的映像具有相同的压缩算法。

安装所需包/库的命令:

sudo apt update  
sudo apt-get install -y python3 python3-pip  
sudo pip3 install libconf zstandard

使用 DiffGen 创建增量更新

DiffGen 工具使用多个参数运行。 所有参数都是必需的,整体语法如下所示:

DiffGenTool [source_archive] [target_archive] [output_path] [log_folder] [working_folder] [recompressed_target_archive]

  • 运行脚本 recompress_tool.py 来创建文件 [recompressed_target_archive],然后使用该文件而不是 [target_archive] 作为创建差异的目标文件。
  • [recompressed_target_archive] 中的映像文件会使用 zstd 进行压缩。

如果 SWU 文件已签名(这是非常有可能的),则还需要另一个参数:

DiffGenTool [source_archive] [target_archive] [output_path] [log_folder] [working_folder] [recompressed_target_archive] "[signing_command]"

  • 除了使用 [recompressed_target_archive] 作为目标文件外,提供签名命令字符串参数会运行 recompress_and_sign_tool.py 来创建文件 [recompressed_target_archive],并对存档中的 sw-description 文件签名(这表示会有一份 sw-description.sig 文件)。 可以使用 Azure/iot-hub-device-update-delta GitHub 存储库中的示例 sign_file.sh 脚本。 打开脚本并对其进行编辑,以将路径添加到私钥文件,然后保存该脚本。 有关示例用法,请参阅示例部分。

下表更加详细地描述了参数:

参数 说明
[source_archive] 这是创建增量时的基础映像。 重要说明:此映像必须与设备上已存在的映像(例如从上一次更新中缓存的映像)相同。
[target_archive] 这是增量将设备更新到的映像。
[output_path] 差异文件创建后在主机上放置的路径(包括正在生成的增量文件的所需名称)。 如果路径不存在,该工具将创建它。
[log_folder] 主机上的路径,会在其中创建日志。 建议将此位置定义为输出路径的子文件夹。 如果路径不存在,该工具将创建它。
[working_folder] 计算机上的路径,用于在增量生成期间放置附件和其他工作文件。 建议将此位置定义为输出路径的子文件夹。 如果路径不存在,该工具将创建它。
[recompressed_target_archive] 在主机上创建重新压缩目标文件的路径。 使用此文件而不是 target_archive 作为差异生成的目标文件<>。 如果在调用 DiffGenTool 之前存在此路径,则路径会被覆盖。 建议将此路径定义为输出路径的子文件夹中的一个文件。
“[signing_command]”(可选) 一个可自定义的命令,用于对重新压缩的存档文件中的 sw-description 文件进行签名。 重新压缩的存档中的 sw-description 文件用作签名命令的输入参数;DiffGenTool 要求签名命令通过追加的 .sig 使用输入的名称创建新的签名文件。 需要使用双引号括起参数,以便将整个命令作为单个参数传入。 此外,请避免将“~”字符放在用于签名的密钥路径中,并改用完整的主路径(例如,请使用 /home/USER/keys/priv.pem 而不是 ~/keys/priv.pem)。

DiffGen 示例

在下面的示例中,我们在 WSL 中使用 /mnt/o/temp 目录进行操作:

创建输入源文件和重新压缩的目标文件之间的差异:

sudo ./DiffGenTool  
/mnt/o/temp/[source file.swu]  
/mnt/o/temp/[target file.swu]  
/mnt/o/temp/[delta file to be created]  
/mnt/o/temp/logs  
/mnt/o/temp/working  
/mnt/o/temp/[recompressed file to be created.swu]

如果还使用签名参数(在 SWU 文件已签名的情况下需要),则可以使用之前参考的示例 sign_file.sh 脚本。 首先,打开脚本并对其进行编辑,以将路径添加到私钥文件。 保存脚本,然后运行 DiffGen,如下所示:

创建输入源文件和重新压缩/重新签名的目标文件之间的差异:

sudo ./DiffGenTool  
/mnt/o/temp/[source file.swu]
/mnt/o/temp/[target file.swu]   
/mnt/o/temp/[delta file to be created]  
/mnt/o/temp/logs  
/mnt/o/temp/working  
/mnt/o/temp/[recompressed file to be created.swu]  
/mnt/o/temp/[path to script]/sign_file.sh

导入生成的增量更新

将更新导入到设备更新服务的基本过程对于增量更新也是一样的,因此请务必查看此页面(如果尚未查看):如何准备要导入 Azure Device Update for IoT Hub 的更新

生成导入清单

将更新导入设备更新服务的第一步始终是创建导入清单(如果还没有)。 有关导入清单的详细信息,请参阅将更新导入设备更新。 对于增量更新,导入清单需要引用两个文件:

  • 运行 DiffGen 工具时创建的重新压缩的目标 SWU 映像。
  • 运行 DiffGen 工具时创建的差异文件。

增量更新功能使用名为相关文件的功能,该功能需要版本 5 或更高版本的导入清单。

若要使用“相关文件”功能为增量更新创建导入清单,需要将 relatedFilesdownloadHandler 对象添加到导入清单。

使用 relatedFiles 对象指定有关增量更新文件的信息,包括文件名、文件大小和 sha256 哈希。 请注意,还需要指定增量更新功能特有的两个属性:

"properties": {
      "microsoft.sourceFileHashAlgorithm": "sha256",
      "microsoft.sourceFileHash": "[insert the source SWU image file hash]"
}

上述两个属性都特定于源 SWU 映像文件,在创建增量更新时,该文件用作 DiffGen 工具的输入。 即使实际上不导入源映像,导入清单中也需要有与源 SWU 映像有关的信息。 下载增量后,设备上的增量组件使用此有关源映像的元数据在设备上查找映像。

使用 downloadHandler 对象指定 Device Update 代理如何使用“相关文件”功能来协调增量更新。 除非要为增量功能自定义自己的设备更新代理版本,否则应仅使用此 downloadHandler:

"downloadHandler": {
  "id": "microsoft/delta:1"
}

可以使用 Azure 命令行接口 (CLI) 为增量更新生成导入清单。 如果你之前未使用过 Azure CLI 来创建导入清单,请参阅创建基本导入清单

az iot du update init v5
--update-provider <replace with your Provider> --update-name <replace with your update Name> --update-version <replace with your update Version> --compat manufacturer=<replace with the value your device will report> model=<replace with the value your device will report> --step handler=microsoft/swupdate:2 properties=<replace with any desired handler properties (JSON-formatted), such as '{"installedCriteria": "1.0"}'> --file path=<replace with path(s) to your update file(s), including the full file name> downloadHandler=microsoft/delta:1 --related-file path=<replace with path(s) to your delta file(s), including the full file name> properties='{"microsoft.sourceFileHashAlgorithm": "sha256", "microsoft.sourceFileHash": "<replace with the source SWU image file hash>"}' 

将生成的导入清单 JSON 保存为扩展名为 .importmanifest.json 的文件

使用 Azure 门户导入

创建导入清单后,即可导入增量更新。 若要导入,请按照向 Device Update for IoT Hub 新增更新中的说明操作。 导入时必须包含以下项:

  • 在上一步中创建的导入清单 .json 文件。
  • 运行 DiffGen 工具时创建的重新压缩的目标 SWU 映像。
  • 运行 DiffGen 工具时创建的差异文件。

将增量更新部署到设备

在 Azure 门户中,部署增量更新时的体验看起来与部署常规映像更新时相同。 有关部署更新的详细信息,请参阅使用 Device Update for Azure IoT Hub 部署更新

为增量更新创建部署后,设备更新服务和客户端将自动识别所部署的每个设备是否存在有效的增量更新。 如果找到有效的增量,则会在该设备上下载并安装增量更新。 回退措施:如果未找到有效的增量更新,则将下载完整的映像更新(重新压缩的目标 SWU 映像)。 此方法可确保要将更新部署到的所有设备都达到相应的版本。

增量更新部署有三种可能的结果:

  • 成功安装增量更新。 设备处于新版本。
  • 增量更新不可用或安装失败,但成功完成了完整映像的回退安装。 设备处于新版本。
  • 对完整映像的增量更新和回退安装都已失败。 设备仍处于旧版本。

要确定自己的结果是上述哪一类,可以通过选择处于失败状态的任何设备来查看带有错误代码和扩展错误代码的安装结果。 如果需要,还可以从多个失败设备收集日志

如果增量更新成功,设备显示“成功”状态。

如果增量更新失败,但成功回退到完整映像,显示以下错误状态:

  • resultCode:[值大于 0]
  • extendedResultCode:[非零值]

如果更新不成功,显示可通过以下说明进行解读的错误状态:

  • result.h 中的设备更新代理错误开始。

    • 设备更新代理中针对用于增量更新的下载处理程序功能的错误以 0x9 开头:

      组件 十进制 Hex 注意
      EXTENSION_MANAGER 0 0x00 指示扩展管理器下载处理程序逻辑中的错误。 示例:0x900XXXXX
      PLUGIN 1 0x01 指示使用下载处理程序插件共享库时出现的错误。 示例:0x901XXXXX
      RESERVED 2 - 7 0x02 - 0x07 保留以用于表示下载处理程序错误。 示例:0x902XXXXX
      COMMON 8 0x08 指示增量下载处理程序扩展顶级逻辑中的错误。 示例:0x908XXXXX
      SOURCE_UPDATE_CACHE 9 0x09 指示增量下载处理程序扩展源更新缓存中的错误。 示例:0x909XXXXX
      DELTA_PROCESSOR 10 0x0A 增量处理器 API 中的错误的错误代码。 示例:0x90AXXXXX
    • 如果 result.h 中不存在错误代码,则可能是增量处理器组件(与设备更新代理分开)中的错误。 在此情况下,extendedResultCode 将是以下十六进制格式的负十进制值:0x90AXXXXX

      • 9 是表示与增量有关的标志
      • 0A 是“增量处理器组件”(ADUC_COMPONENT_DELTA_DOWNLOAD_HANDLER_DELTA_PROCESSOR)
      • XXXXX 是 FIT 增量处理器的 20 位错误代码
  • 如果无法根据错误代码信息解决问题,请提交 GitHub 问题以获取进一步的帮助。

后续步骤

排查常见问题