AWS IoT Greengrass
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

在 AWS IoT Greengrass 核心上运行 Lambda 函数

AWS IoT Greengrass 为用户定义的代码提供了容器化 Lambda 运行时环境。部署到 AWS IoT Greengrass Core的 Lambda 函数在核心的本地 Lambda 运行时环境中运行。本地事件、云中的消息和其他来源可能会触发本地 Lambda 函数,这会为连接的设备提供本地计算功能。例如,您可以使用 Greengrass Lambda 函数筛选设备数据,然后再将数据传输到云。

要将 Lambda 函数部署到核心,您需要将该函数添加到一个 Greengrass 组(通过引用现有的 Lambda 函数),为该函数配置组特定的设置,然后部署该组。如果该函数访问 AWS 服务,您还必须在组角色中添加任何所需的权限。

您可以配置确定 Lambda 函数运行方式的参数,包括权限、隔离、内存限制等。有关更多信息,请参阅使用组特定配置控制 Greengrass Lambda 函数的执行

注意

这些设置还可用于在 Docker 容器中运行 AWS IoT Greengrass。有关更多信息,请参阅在 Docker 容器中运行 AWS IoT Greengrass

下表列出了受支持的 AWS Lambda 运行时以及它们可以运行的 AWS IoT Greengrass 核心软件的版本。

语言或平台 GGC 版本
Python 2.7 1.0 或更高版本
Python 3.7 1.9
Java 8 11 或更高版本
Node.js 6.10 11 或更高版本
Node.js 8.10 1.9
C、C++ 1.6 or later

Greengrass Lambda 函数的开发工具包

AWS 提供三个开发工具包可供 AWS IoT Greengrass Core上运行的 Greengrass Lambda 函数使用。这些开发工具包在不同的软件包中,因此,函数可以同时使用它们。要在 Greengrass Lambda 函数中使用软件开发工具包,请将其包含在您的部署软件包中。

AWS IoT Greengrass Core 开发工具包

允许本地 Lambda 函数与核心交互以执行:

  • 与 AWS IoT 交换 MQTT 消息。

  • 与 Greengrass 组中的连接器、设备及其他 Lambda 函数交换 MQTT 消息。

  • 与本地影子服务交互。

  • 调用其他本地 Lambda 函数。

  • 访问秘密资源

AWS IoT Greengrass 在 GitHub 上用以下语言和平台提供了 AWS IoT Greengrass Core 开发工具包。

如果您正在运行 Python Lambda 函数,则也可使用 pip 在核心设备上安装适用于 Python 的 AWS IoT Greengrass Core 开发工具包。然后,您可以在 Lambda 函数部署程序包中部署您的函数而不包括开发工具包。有关更多信息,请参阅 greengrasssdk

注意

要使用 pip 来安装 Python 开发工具包,请在您的核心设备终端中运行以下命令。

pip install greengrasssdk
AWS IoT Greengrass机器学习 SDK

允许本地 Lambda 函数使用部署到 Greengrass 核心的机器学习模型作为机器学习资源。Lambda 可以使用此开发工具包调用作为连接器部署到核心的本地推理服务并与其交互。有关更多信息,包括使用此开发工具包的代码示例,请参阅图像分类连接器。

下表列出了支持的语言或平台以及可以在其中运行的 AWS IoT Greengrass 核心软件版本。

语言或平台 GGC 版本
Python 2.7 1.7 or later

有关下载信息,请参阅AWS IoT Greengrass ML 开发工具包软件

AWS 开发工具包

允许本地 Lambda 函数对 AWS 服务进行直接调用,如 Amazon S3、DynamoDB、AWS IoT 和 AWS IoT Greengrass。要在 Greengrass Lambda 函数中使用 AWS 开发工具包,必须将其包含在部署软件包中。在将同一程序包中的 AWS 开发工具包用作 AWS IoT Greengrass 核心开发工具包时,请确保 Lambda 函数使用正确的命名空间。在核心处于脱机状态时,Greengrass Lambda 函数无法与云服务进行通信。

入门资源中心下载相应的 AWS 开发工具包。

有关创建部署程序包的更多信息,请参阅入门教程中的创建并打包 Lambda 函数AWS Lambda Developer Guide中的创建部署程序包

迁移基于云的 Lambda 函数

AWS IoT Greengrass 核心开发工具包采用 AWS 开发工具包编程模型,从而轻松将为云开发的 Lambda 函数移植到在 AWS IoT Greengrass Core上运行的 Lambda 函数。

例如,以下 Python Lambda 函数使用适用于 Python 的 AWS 开发工具包将消息发布到云中的 some/topic 主题:

import boto3 client = boto3.client('iot-data') response = client.publish( topic = 'some/topic', qos = 0, payload = 'Some payload'.encode() )

要为 AWS IoT Greengrass Core移植该函数,请在 import 语句和 client 初始化中将 boto3 模块名称更改为 greengrasssdk,如以下示例所示:

import greengrasssdk client = greengrasssdk.client('iot-data') response = client.publish( topic = 'some/topic', qos = 0, payload = 'Some payload'.encode() )

注意

AWS IoT Greengrass 核心开发工具包仅支持发送 QoS 为 0 的 MQTT 消息。

利用编程模型之间的相似性,还可以使用最少的工作量在云中开发 Lambda 函数,然后将其迁移到 AWS IoT Greengrass。Lambda 可执行文件 无法在云中运行,因此,您无法在部署之前使用 AWS 开发工具包在云中对其进行开发。

按别名或版本引用 Lambda 函数

Greengrass 组可以按别名 (推荐) 或版本引用 Lambda 函数。通过使用别名,可以更轻松地管理代码更新,因为您在更新函数代码时无需更改订阅表或组定义。相反,您只是将别名指向新的函数版本。 在组部署期间,别名将解析为版本号。在使用别名时,解析的版本将在部署时更新为别名指向的版本。

AWS IoT Greengrass 不支持 $LATEST 版本的 Lambda 别名。 $LATEST 版本未绑定到发布的不可变函数版本,可以随时对其进行更改,这与 AWS IoT Greengrass 版本不可变原则相反。

使用代码更改更新 Greengrass Lambda 函数的常见做法是,在 Greengrass 组和订阅中使用名为 PRODUCTION 的别名。在将 Lambda 函数的新版本提升到生产环境时,请将别名指向最新的稳定版本,然后重新部署组。您也可以使用这种方法回滚到以前的版本。

Greengrass Lambda 函数的通信流

Greengrass Lambda 函数支持多种与 AWS IoT Greengrass 组 的其他成员、本地服务和云服务(包括 AWS 服务)通信的方法。

使用 MQTT 消息进行通信

Lambda 函数可以使用由订阅控制的发布-订阅模式发送和接收 MQTT 消息。

此通信流能让 Lambda 函数与以下实体交换消息:

  • 组中的设备。

  • 组中的连接器。

  • 组中的其他 Lambda 函数。

  • AWS IoT。

  • 本地设备影子服务。

订阅会定义消息源、消息目标以及用于将消息从源路由到目标的主题。发布到 Lambda 函数的消息将传递到为该函数注册的处理程序。订阅实现了更高的安全性并提供可预测的交互。有关更多信息,请参阅 Greengrass 消息收发工作流程

注意

在核心处于脱机状态时,Greengrass Lambda 函数可以与设备、连接器、其他函数和本地影子交换消息,但将到 AWS IoT 的消息排入队列。有关更多信息,请参阅MQTT 消息队列

其他通信流

  • 为了与核心设备上的本地资源和机器学习模型进行交互,Greengrass Lambda 函数使用平台特定的操作系统接口。例如,您可以在 Python 2.7 函数中使用 os 模块中的 open 方法。要允许函数访问某个资源,函数必须与该资源关联,或者为其授予了 read-onlyread-write 权限。有关更多信息(包括 AWS IoT Greengrass Core 版本可用性),请参阅 使用 Lambda 函数和连接器访问本地资源执行机器学习推理

    注意

    如果您在不进行容器化的情况下运行 Lambda 函数,则无法使用附加的本地资源,并且必须直接访问这些资源。对于在未进行容器化的情况下运行的 Lambda 函数,机器学习资源不可用。

  • Greengrass Lambda 函数可以使用 AWS 开发工具包与 AWS 服务进行通信。有关更多信息,请参阅 AWS 开发工具包

  • Greengrass Lambda 函数可以使用第三方接口与外部云服务进行通信,类似于基于云的 Lambda 函数。

注意

在核心处于脱机状态时,Greengrass Lambda 函数无法与 AWS 或其他云服务进行通信。

检索输入 MQTT 主题(或主旨)

AWS IoT Greengrass 使用订阅来控制在设备、Lambda 函数以及组中的连接器之间交换 MQTT 消息以及与 AWS IoT 或本地影子服务交换 MQTT 消息。订阅定义消息源、消息目标以及用于路由消息的 MQTT 主题。当目标是一个 Lambda 函数时,当源发布消息时将调用该函数的处理程序。有关更多信息,请参阅 使用 MQTT 消息进行通信

以下示例显示 Lambda 函数如何可以从传递给处理程序的 context 获取输入主题。具体方法是通过从上下文层次结构 (context.client_context.custom['subject']) 访问 subject 密钥。该示例还会解析输入 JSON 消息,然后发布解析的主题和消息。

注意

在 AWS IoT Greengrass API 中,订阅的主题由 subject 属性表示。

import greengrasssdk import logging client = greengrasssdk.client('iot-data') OUTPUT_TOPIC = 'test/topic_results' def get_input_topic(context): try: topic = context.client_context.custom['subject'] except Exception as e: logging.error('Topic could not be parsed. ' + repr(e)) return topic def get_input_message(event): try: message = event['test-key'] except Exception as e: logging.error('Message could not be parsed. ' + repr(e)) return message def function_handler(event, context): try: input_topic = get_input_topic(context) input_message = get_input_message(event) response = 'Invoked on topic "%s" with message "%s"' % (input_topic, input_message) logging.info(response) except Exception as e: logging.error(e) client.publish(topic=OUTPUT_TOPIC, payload=response) return

要测试函数,请使用默认配置设置将其添加到组中。然后,添加以下订阅并部署该组。有关说明,请参阅模块 3(第 1 部分):AWS IoT Greengrass 上的 Lambda 函数

目标 主题筛选条件
IoT 云 此函数 test/input_message
此函数 IoT 云 test/topic_results

部署完成后,调用该函数。

  1. 在 AWS IoT 控制台中,打开 Test (测试) 页面。

  2. 订阅 test/topic_results 主题。

  3. 将消息发布到 test/input_message 主题。对于此示例,您必须在 JSON 消息中包含 test-key 属性。

    { "test-key": "Some string value" }

    如果成功,此函数会将输入主题和消息字符串发布到 test/topic_results 主题。

Greengrass Lambda 函数的生命周期配置

Greengrass Lambda 函数生命周期确定函数何时启动以及它如何创建和使用容器。生命周期还确定如何保留位于函数处理程序外部的变量和预处理逻辑。

AWS IoT Greengrass 支持按需(默认)或长时间生存的生命周期:

  • 按需函数在调用时启动,并在没有要执行的任务时停止。除非具有可重复使用的现有容器,否则,函数调用将创建单独的容器(或沙盒)以处理调用。发送到函数的数据可以由任何容器提取。

    按需函数的多次调用可以并行运行。

    在创建新的容器时,不会保留在函数处理程序外部定义的变量和预处理逻辑。

  • 长时间生存的(或固定的)函数在 AWS IoT Greengrass Core启动时自动启动,并在单个容器中运行。发送到函数的所有数据由相同的容器提取。

    多个调用将排入队列,直到执行了以前的调用。

    将为处理程序的每次调用保留在函数处理程序外部定义的变量和预处理逻辑。

    如果需要在没有任何初始输入的情况下开始工作,长时间生存的 Lambda 函数是非常有用的。例如,在长时间存在的函数开始接收设备数据时,该函数可以加载并开始处理 ML 模型以使其准备就绪。

    注意

    请记住,长时间生存的函数具有与其处理程序调用关联的超时。如果要执行无限期运行的代码,您必须在处理程序外部启动该代码。确保在处理程序外部没有阻止代码而导致函数可能无法完成初始化。

    这些函数将运行,除非核心停止(例如,在组部署或设备重启期间)或函数进入错误状态(例如,处理程序超时、未捕获的异常或者当它超过其内存限制时)。

有关容器重复使用的更多信息,请参阅 AWS 计算博客上的了解 AWS Lambda 中的容器重复使用

Lambda 可执行文件

此功能适用于 AWS IoT Greengrass Core v1.6 及更高版本。

Lambda 可执行文件是一种 Greengrass Lambda 函数,可用于在核心环境中运行二进制代码。这样,您就可以在本地执行设备特定的功能,并从较小的编译代码占用空间中受益。Lambda 可执行文件可以由事件调用,它调用其他函数以及访问本地资源。

Lambda 可执行文件仅支持二进制编码类型(不支持 JSON),但您可以像其他 Greengrass Lambda 函数一样在 Greengrass 组中管理这些函数并进行部署。不过,创建 Lambda 可执行文件的过程与创建 Python、Java 和 Node.js Lambda 函数不同:

  • 您无法使用 AWS Lambda 控制台创建(或管理)Lambda 可执行文件。您只能使用 AWS Lambda API 创建 Lambda 可执行文件。

  • 您将函数代码作为包含 适用于 C 的 AWS IoT Greengrass Core 开发工具包 的编译可执行文件上传到 AWS Lambda。

  • 您将可执行文件名称指定为函数处理程序。

Lambda 可执行文件必须在其函数代码中实施某些调用和编程模式。例如,main 方法必须:

  • 调用 gg_global_init 以初始化 Greengrass 内部全局变量。必须先调用该函数,然后再创建任何线程以及调用任何其他 AWS IoT Greengrass 核心开发工具包函数。

  • 调用 gg_runtime_start 以在 Greengrass Lambda 运行时环境中注册函数处理程序。必须在初始化时调用该函数。调用该函数将导致运行时环境使用当前线程。可选的 GG_RT_OPT_ASYNC 参数指示该函数不要阻止,而是为运行时环境创建新的线程。该函数使用 SIGTERM 处理程序。

以下代码段是 GitHub 上的 simple_handler.c 代码示例中的 main 方法。

int main() { gg_error err = GGE_SUCCESS; err = gg_global_init(0); if(err) { gg_log(GG_LOG_ERROR, "gg_global_init failed %d", err); goto cleanup; } gg_runtime_start(handler, 0); cleanup: return -1; }

有关要求、限制和其他实施细节的更多信息,请参阅适用于 C 的 AWS IoT Greengrass Core 开发工具包

创建 Lambda 可执行文件

在编译代码以及开发工具包后,请使用 AWS Lambda API 创建 Lambda 函数并上传编译的可执行文件。

注意

必须使用与 C89 兼容的编译器编译您的函数。

以下示例使用 create-function CLI 命令创建 Lambda 可执行文件。该命令指定:

  • 处理程序的可执行文件名称。它必须是编译的可执行文件的确切名称。

  • 包含编译的可执行文件的 .zip 文件的路径。

  • 运行时环境的 arn:aws-cn:greengrass:::runtime/function/executable。这是所有 Lambda 可执行文件的运行时。

注意

对于 role,您可以指定任何 Lambda 执行角色的 ARN。AWS IoT Greengrass 不使用该角色,但需要使用该参数以创建函数。有关 Lambda 执行角色的更多信息,请参阅 AWS Lambda Developer Guide中的 AWS Lambda 权限模型

aws lambda create-function \ --region aws-region \ --function-name function-name \ --handler executable-name \ --role role-arn \ --zip-file fileb://file-name.zip \ --runtime arn:aws-cn:greengrass:::runtime/function/executable

接下来,使用 AWS Lambda API 发布一个版本并创建别名。

  • 使用 publish-version 发布一个函数版本。

    aws lambda publish-version \ --function-name function-name \ --region aws-region
  • 使用 create-alias 创建指向刚发布的版本的别名。在将 Lambda 函数添加到 Greengrass 组时,我们建议您按别名引用这些函数。

    aws lambda create-alias \ --function-name function-name \ --name alias-name \ --function-version version-number \ --region aws-region

注意

AWS Lambda 控制台不显示 Lambda 可执行文件。要更新函数代码,您还必须使用 Lambda API。

接下来,将 Lambda 可执行文件添加到一个 Greengrass 组,在组特定的设置中将其配置为接受二进制输入数据,然后部署该组。您可以在 AWS IoT Greengrass 控制台 中或者使用 AWS IoT Greengrass API 执行此操作。