教程:预配地理延迟

本教程介绍如何使用分配策略将多个模拟对称密钥设备安全地预配到一组 IoT 中心。 IoT 中心设备预配服务 (DPS) 通过其内置的分配策略和其对自定义分配策略的支持,支持各种分配方案。

预配“地理位置/地理延迟”是一种常见的分配方案。 当设备在两位置之间移动时,通过将设备预配到距离每个位置最近的 IoT 中心来改善网络延迟。 在此方案中,为注册选择跨越区域的一组 IoT 中心。 为这些注册选择内置“最低延迟”分配策略。 此策略会使设备预配服务评估设备延迟,并从一组 IoT 中心确定最接近的 IoT 中心。

本教程使用 Azure IoT C SDK 中的模拟设备示例来演示如何跨区域预配设备。 我们将在本教程中执行以下步骤:

  • 使用 Azure CLI 来创建两个区域性 IoT 中心(“中国北部 2”和“中国东部” )
  • 创建基于地理位置(最低延迟)来预配设备的注册
  • 使用 Azure CLI 来创建两个区域性 Linux VM,以充当相同区域(“中国北部 2”和“中国东部”)中的设备
  • 在这两个 Linux VM 上为 Azure IoT C SDK 设置开发环境
  • 模拟设备,并验证是否已将设备预配到最近区域中的 IoT 中心。

重要

某些地区可能会不时对虚拟机的创建实施限制。 在编写本指南时,“chinanorth2”和“chinaeast”区域允许创建 VM 。 如果无法在其中一个区域创建 VM,可以尝试在其他区域中创建。 若要了解有关在创建 VM 时选择 Azure 地理区域的详细信息,请参阅 Azure 中虚拟机的区域

先决条件

  • 如需在本地运行 CLI 参考命令,请安装 Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI

    • 如果使用的是本地安装,请使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅使用 Azure CLI 登录

    • 出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展详细信息,请参阅使用 Azure CLI 的扩展

    • 运行 az version 以查找安装的版本和依赖库。 若要升级到最新版本,请运行 az upgrade

创建两个区域 IoT 中心

在本部分,我们将创建一个 Azure 资源组和两个新的区域性 IoT 中心资源。 一个 IoT 中心将用于“中国北部 2”区域,而另一个将用于“中国东部”区域 。

重要

建议对本教程中创建的所有资源使用相同的资源组。 这将便于在完成学习后更为轻松地清理创建的资源。

  1. 在 Azure Cloud Shell 中,使用以下 az group create 命令来创建资源组:

    az group create --name contoso-us-resource-group --location chinaeast
    
  2. 在“chinaeast”位置创建 IoT 中心,并将它添加到使用以下 az iot hub create 命令创建的资源组(将 {unique-hub-name} 替换为你自己独一无二的名称):

    az iot hub create --name {unique-hub-name} --resource-group contoso-us-resource-group --location chinaeast --sku S1
    

    此命令可能需要花费几分钟时间完成。

  3. 现在,在“chinanorth2”位置创建 IoT 中心,并将它添加到使用以下 az iot hub create 命令创建的资源组(将 {unique-hub-name} 替换为你自己独一无二的名称):

    az iot hub create --name {unique-hub-name} --resource-group contoso-us-resource-group --location chinanorth2 --sku S1
    

    此命令可能需要花费几分钟时间完成。

为地理延迟创建注册

在这一部分,你将为设备创建新的注册组。

为简单起见,本教程将在注册中使用对称密钥证明。 对于更安全的解决方案,请考虑使用具有信任链的 X.509 证书证明

  1. 登录到 Azure 门户,并导航到设备预配服务实例。

  2. 从导航菜单的“设置”部分选择“管理注册”。

  3. 选择“添加注册组”。

  4. 在“添加注册组”页的“注册 + 预配”选项卡上,提供以下信息以配置注册组详细信息:

    字段 说明
    证明 选择“对称密钥”作为证明类型
    对称密钥设置 选中“自动生成对称密钥”复选框。
    组名 将组命名为 contoso-us-devices,或提供你自己的组名称。 注册组名称是一个不区分大小写的字符串(最大长度为 128 个字符),包含字母数字字符和以下特殊字符:'-''.''_'':'。 最后一个字符必须是字母数字或短划线 ('-')。
  5. 选择“下一步:IoT 中心”。

  6. 使用以下步骤将两个 IoT 中心添加到注册组:

    1. 在“添加注册组”页的“IoT 中心”选项卡上,在“目标 IoT 中心”部分选择“添加 IoT 中心链接”。

    2. 在“添加 IoT 中心链接”页上,选择在 chinaeast 区域中创建的 IoT 中心,并为其分配 iothubowner 访问权限。

    3. 选择“保存”。

    4. 再次选择“添加 IoT 中心链接”,并按照相同的步骤添加在 chinanorth2 区域中创建的 IoT 中心。

    5. 在“目标 IoT 中心”下拉菜单中,选择这两个 IoT 中心。

  7. 对于“分配策略”,请选择“最低延迟”。

  8. 选择“查看 + 创建”。

  9. 在“审阅 + 创建”选项卡上,验证你的全部值,然后选择“创建”。

  10. 创建注册组后,从注册组列表中选择其名称 contoso-us-devices

  11. 复制“主密钥”。 此密钥稍后将会在为这两个模拟设备生成唯一设备密钥时使用。

创建区域 Linux VM

在本部分,请创建两个区域 Linux 虚拟机 (VM),一个在“中国北部 2”,一个在“中国东部 2”。 这些 VM 将从每个区域运行设备模拟示例,以演示这两个区域中针对设备的设备预配。

为了更轻松地清理资源,请将这些 VM 添加到包含创建的 IoT 中心的同一资源组 contoso-us-resource-group

  1. 在 Azure 本地 Shell 中,更改以下命令中的以下参数,然后运行该命令来创建“中国东部”区域 VM:

    --name:为“中国东部”区域设备 VM 输入一个唯一名称。

    --admin-username:使用你自己的管理员用户名称。

    --admin-password:使用你自己的管理员密码。

    az vm create \
    --resource-group contoso-us-resource-group \
    --name ContosoSimDeviceEast \
    --location chinaeast \
    --image Canonical:UbuntuServer:18.04-LTS:18.04.201809110 \
    --admin-username contosoadmin \
    --admin-password myContosoPassword2018 \
    --authentication-type password
    --public-ip-sku Standard
    

    此命令需要花费几分钟时间完成。

  2. 在该命令完成后,复制“中国东部”区域 VM 的 publicIpAddress 值。

  3. 在 Azure 本地 Shell 中,更改该命令中的以下参数,然后运行该命令来创建“中国北部 2”区域 VM:

    --name:为“中国北部 2”区域性设备 VM 输入独一无二的名称 。

    --admin-username:使用你自己的管理员用户名称。

    --admin-password:使用你自己的管理员密码。

    az vm create \
    --resource-group contoso-us-resource-group \
    --name ContosoSimDeviceWest2 \
    --location chinanorth2 \
    --image Canonical:UbuntuServer:18.04-LTS:18.04.201809110 \
    --admin-username contosoadmin \
    --admin-password myContosoPassword2018 \
    --authentication-type password
    --public-ip-sku Standard
    

    此命令需要花费几分钟时间完成。

  4. 在该命令完成后,复制“中国北部 2”区域 VM 的 publicIpAddress 值。

  5. 打开两个命令行 shell。

  6. 使用 SSH 连接到每个 shell 中的其中一个区域 VM。

    将你作为参数复制的管理员用户名和公共 IP 地址传递给 SSH。 在出现提示时输入管理员密码。

    ssh contosoadmin@1.2.3.4
    
    contosoadmin@ContosoSimDeviceEast:~$
    
    ssh contosoadmin@5.6.7.8
    
    contosoadmin@ContosoSimDeviceWest:~$
    

准备 Azure IoT C SDK 开发环境

在这一部分,你将克隆每个 VM 上的 Azure IoT C SDK。 SDK 包含将从每个区域模拟设备预配的示例。

对于每个 VM:

  1. ,使用以下命令安装 CMake 、g++ 、gcc 和 Git

    sudo apt-get update
    sudo apt-get install cmake build-essential libssl-dev libcurl4-openssl-dev uuid-dev git-all
    
  2. 找到并复制最新版 SDK 的标记名称。

  3. 在这两个 VM 上克隆 Azure IoT C SDK。 使用在上一步找到的标记作为 -b 参数的值:

    git clone -b <release-tag> https://github.com/Azure/azure-iot-sdk-c.git
    cd azure-iot-sdk-c
    git submodule update --init
    

    应该预料到此操作需要几分钟才能完成。

  4. 在存储库内创建一个新的 cmake 文件夹,并更改为该文件夹。

    mkdir ~/azure-iot-sdk-c/cmake
    cd ~/azure-iot-sdk-c/cmake
    
  5. 运行以下命令,生成特定于你的开发客户端平台的 SDK 版本:

    cmake -Dhsm_type_symm_key:BOOL=ON -Duse_prov_client:BOOL=ON  ..
    
  6. 生成成功后,最后的几个输出行如下所示:

    -- IoT Client SDK Version = 1.7.0
    -- Provisioning SDK Version = 1.7.0
    -- Looking for include file stdint.h
    -- Looking for include file stdint.h - found
    -- Looking for include file stdbool.h
    -- Looking for include file stdbool.h - found
    -- target architecture: x86_64
    -- Performing Test CXX_FLAG_CXX11
    -- Performing Test CXX_FLAG_CXX11 - Success
    -- Found OpenSSL: /usr/lib/x86_64-linux-gnu/libcrypto.so (found version "1.1.1")
    -- Found CURL: /usr/lib/x86_64-linux-gnu/libcurl.so (found version "7.58.0")
    -- Found CURL: /usr/lib/x86_64-linux-gnu/libcurl.so
    -- target architecture: x86_64
    -- iothub architecture: x86_64
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/contosoadmin/azure-iot-sdk-c/azure-iot-sdk-c
    

派生唯一设备密钥

在组注册中使用对称密钥证明时,不会直接使用注册组密钥。 而是你自己从每个设备的注册组密钥派生唯一密钥。

在本教程的这一部分中,你将从您的组主密钥生成一个设备密钥,以计算设备唯一注册 ID 的 HMAC-SHA256。 然后,结果将转换为 Base64 格式。

重要

不要在设备代码中包含你的组主键。

对于 chinaeast 和 chinanorth2 两种设备:

  1. 使用 openssl 生成唯一密钥。 将使用以下 Bash shell 脚本(将 {primary-key} 替换为之前复制的注册组的主键,并将 {contoso-simdevice} 替换为您自己的每个设备的唯一注册 ID。 注册 ID 是一个不区分大小写的字符串(最大长度为 128 个字符),包含字母数字字符和以下特殊字符:'-''.''_'':'。 最后一个字符必须是字母数字或短划线 ('-')。

    KEY={primary-key}
    REG_ID={contoso-simdevice}
    
    keybytes=$(echo $KEY | base64 --decode | xxd -p -u -c 1000)
    echo -n $REG_ID | openssl sha256 -mac HMAC -macopt hexkey:$keybytes -binary | base64
    
  2. 该脚本将输出类似于如下密钥:

    p3w2DQr9WqEGBLUSlFi1jPQ7UWQL4siAGy75HFTFbf8=
    
  3. 现在,每个设备都有自己的派生设备密钥和唯一的注册 ID,可以在预配过程中与注册组执行对称密钥证明。

模拟来自每个区域的设备

在这一部分,你将为这两个区域 VM 更新 Azure IoT C SDK 中的预配示例。

示例代码模拟将预配请求发送到你的设备预配服务实例的设备启动序列。 启动序列将会使设备被识别,并基于延迟被分配到最邻近的 IoT 中心。

  1. 在 Azure 门户中,选择设备预配服务的“概述”选项卡,记下“ID 范围”的值 。

    Extract Device Provisioning Service endpoint information from the portal blade.

  2. 在两个 VM 上,都打开 ~/azure-iot-sdk-c/provisioning_client/samples/prov_dev_client_sample/prov_dev_client_sample.c 进行编辑。

    vi ~/azure-iot-sdk-c/provisioning_client/samples/prov_dev_client_sample/prov_dev_client_sample.c
    
  3. 在两个 VM 上,找到 id_scope 常量,将值替换为前面复制的“ID 范围”值。

    static const char* id_scope = "0ne00002193";
    
  4. 在两个 VM 上,在同一文件中找到 main() 函数的定义。 请确保将 hsm_type 变量设置为 SECURE_DEVICE_TYPE_SYMMETRIC_KEY(如下所示),以匹配注册组证明方法。

    将你对文件的更改保存在这两个 VM 上。

    SECURE_DEVICE_TYPE hsm_type;
    //hsm_type = SECURE_DEVICE_TYPE_TPM;
    //hsm_type = SECURE_DEVICE_TYPE_X509;
    hsm_type = SECURE_DEVICE_TYPE_SYMMETRIC_KEY;
    
  5. 在两个 VM 上,都在 prov_dev_client_sample.c 中找到已注释掉的对 prov_dev_set_symmetric_key_info() 的调用。

    // Set the symmetric key if using they auth type
    //prov_dev_set_symmetric_key_info("<symm_registration_id>", "<symmetric_Key>");
    

    取消注释这些函数调用,并将占位符值(包括尖括号)替换为每个设备的唯一注册 ID 以及在上一节中派生的设备的派生设备密钥。 下面显示的密钥是示例。 请使用你之前生成的密钥。

    中国东部:

    // Set the symmetric key if using they auth type
    prov_dev_set_symmetric_key_info("contoso-simdevice-east", "p3w2DQr9WqEGBLUSlFi1jPQ7UWQL4siAGy75HFTFbf8=");
    

    中国北部:

    // Set the symmetric key if using they auth type
    prov_dev_set_symmetric_key_info("contoso-simdevice-west", "J5n4NY2GiBYy7Mp4lDDa5CbEe6zDU/c62rhjCuFWxnc=");
    
  6. 在这两个 VM 上,保存文件。

  7. 在这两个 VM 上,导航到以下所示的示例文件夹,并生成示例。

    cd ~/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_sample/
    cmake --build . --target prov_dev_client_sample --config Debug
    
  8. 在成功生成后,在这两个 VM 上都运行 prov_dev_client_sample.exe,以模拟来自每个区域的设备。 请注意,每个设备将被分配到最邻近模拟设备区域的 IoT 中心。

    运行模拟:

    ~/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_sample/prov_dev_client_sample
    

    中国东部 VM 的示例输出:

    contosoadmin@ContosoSimDeviceEast:~/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_sample$ ./prov_dev_client_sample
    Provisioning API Version: 1.2.9
    
    Registering Device
    
    Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    
    Registration Information received from service: contoso-east-hub.azure-devices.cn, deviceId: contoso-simdevice-east
    Press enter key to exit:
    
    

    中国北部 VM 的示例输出:

    contosoadmin@ContosoSimDeviceWest:~/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_sample$ ./prov_dev_client_sample
    Provisioning API Version: 1.2.9
    
    Registering Device
    
    Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    
    Registration Information received from service: contoso-west-hub.azure-devices.cn, deviceId: contoso-simdevice-west
    Press enter key to exit:
    

清理资源

如果打算继续使用本教程中创建的资源,则可以保留它们。 否则,请使用以下步骤删除本教程创建的所有资源,以避免不必要的费用。

此处的步骤假定你按照名为 contoso-us-resource-group 的同一资源组的指示创建了本教程中的所有资源。

重要

删除资源组的操作不可逆。 资源组以及包含在其中的所有资源将被永久删除。 请确保不要意外删除错误的资源组或资源。 如果在现有的包含要保留资源的资源组中创建了 IoT 中心,则只删除 IoT 中心资源本身,而不要删除资源组。

若要按名称删除资源组:

  1. 登录到 Azure 门户

  2. 选择“资源组”。

  3. 在“按名称筛选...”文本框中,键入包含资源的资源组名称“contoso-us-resource-group”

  4. 在结果列表中的资源组右侧,单击“...”,然后单击“删除资源组”

  5. 系统会要求确认是否删除该资源组。 再次键入资源组的名称进行确认,然后选择“删除” 。 片刻之后,将会删除该资源组及其包含的所有资源。

后续步骤

若要了解有关自定义分配策略的详细信息,请参阅