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

AWS IoT Greengrass Version 1 于 2023 年 6 月 30 日进入延长使用寿命阶段。有关更多信息,请参阅 AWS IoT Greengrass V1维护策略。在此日期之后,AWS IoT Greengrass V1 不再发布更新来提供新功能、功能增强、错误修复或安全补丁。在 AWS IoT Greengrass V1 上运行的设备不会受到干扰,并且将继续运行并连接到云。我们强烈建议您迁移到 AWS IoT Greengrass Version 2,从而添加重要的新功能支持更多平台

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

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

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

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

注意

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

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

语言或平台 GGC 版本
Python 3.8 1.11
Python 3.7 1.9 或更高版本
Python 2.7 * 1.0 或更高版本
Java 8 1.1 或更高版本
Node.js 12.x * 1.10 或更高版本
Node.js 8.10 * 1.9 或更高版本
Node.js 6.10 * 1.1 或更高版本
C、C++ 1.6 或更高版本

* 您可以在支持的 AWS IoT Greengrass 版本上运行使用这些运行时的 Lambda 函数,但无法在 AWS Lambda 中创建它们。如果设备上的运行时与为该函数指定的 AWS Lambda 运行时不同,则可以使用 FunctionDefintionVersionFunctionRuntimeOverride 来选择自己的运行时。有关更多信息,请参阅 CreateFunctionDefinition。有关支持的运行时的更多信息,请参阅AWS Lambda 开发人员指南中的运行时支持策略

Greengrass Lambda 函数的软件开发工具包

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

AWS IoT Greengrass Core 软件开发工具包

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

  • 与 AWS IoT Core 交换 MQTT 消息。

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

  • 与本地影子服务交互。

  • 调用其他的本地 Lambda 函数。

  • 访问密钥资源

  • 流管理器交互。

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

要在 Lambda 函数部署程序包中包含 AWS IoT Greengrass 核心开发工具包依赖项,请执行以下操作:

  1. 下载与 Lambda 函数的运行时匹配的 AWS IoT Greengrass 核心开发工具包程序包的语言或平台。

  2. 解压缩下载的程序包以获取软件开发工具包。软件开发工具包是 greengrasssdk 文件夹。

  3. greengrasssdk 包含在包含函数代码的 Lambda 函数部署程序包中。这是您在创建 Lambda 函数时上传到 AWS Lambda 的程序包。

 

StreamManagerClient

只有以下 AWS IoT Greengrass 核心开发工具包可用于流管理器操作:

  • Java SDK(v1.4.0 或更高版本)

  • Python SDK(v1.5.0 或更高版本)

  • Node.js SDK(v1.6.0 或更高版本)

要使用 AWS IoT Greengrass Core SDK for Python 与流管理器进行交互,必须安装 Python 3.7 或更高版本。您还必须安装依赖项以包含在 Python Lambda 函数部署程序包中:

  1. 导航到包含该 requirements.txt 文件的开发工具包目录。此文件列出了依赖项。

  2. 安装开发工具包依赖项。例如,运行以下 pip 命令将它们安装在当前目录中:

    pip install --target . -r requirements.txt

 

在核心设备上安装 AWS IoT Greengrass Core SDK for Python

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

此支持适用于具有大小限制的核心。我们建议您尽可能将开发工具包包含在 Lambda 函数部署程序包中。

 

AWS IoT Greengrass 机器学习开发工具包

允许本地 Lambda 函数使用作为 ML 资源部署到 Greengrass 核心的机器学习 (ML) 模型。对于作为连接器部署到核心的本地推理服务,Lambda 函数可以使用 SDK 来调用并与之交互。Lambda 函数和 ML 连接器也可以使用软件开发工具包将数据发送到 ML 反馈连接器进行上传和发布。有关更多信息,包括使用此开发工具包的代码示例,请参阅ML 图像分类连接器ML 对象检测连接器ML 反馈连接器

下表列出了对于各开发工具包版本支持的语言或平台以及它们可以在其中运行的 AWS IoT Greengrass 核心软件的版本。

SDK 版本 语言或平台 必需的 GGC 版本 更改日志
1.1.0 Python 3.7 或 2.7 1.9.3 或更高版本 添加了 Python 3.7 支持和新的 feedback 客户端。
1.0.0 Python 2.7 1.7 或更高版本 首次发布。

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

AWS SDK

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

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

有关创建部署程序包的更多信息,请参阅入门教程中的 创建并打包 Lambda 函数AWS Lambda 开发人员指南中的创建部署程序包

迁移基于云的 Lambda 函数

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

例如,以下 Python Lambda 函数使用 AWS SDK for Python (Boto3) 将消息发布到云中的主题 some/topic

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

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

import greengrasssdk iot_client = greengrasssdk.client("iot-data") iot_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 函数的消息将传递到为该函数注册的处理程序。订阅实现了更高的安全性并提供可预测的交互。有关更多信息,请参阅 MQTT 消息传递工作流中的托管订阅

注意

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

其他通信流

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

    注意

    如果您在不进行容器化的情况下运行 Lambda 函数,则无法使用附加的本地设备和卷资源,并且必须直接访问这些资源。

  • Lambda 函数可以使用 AWS IoT Greengrass 核心开发工具包中的 Lambda 客户端来调用 Greengrass 组中的其他 Lambda 函数。

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

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

注意

在核心处于脱机状态时,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 控制台中打开 MQTT 测试客户端页面。

  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 核心启动时自动启动,并在单个容器中运行。发送到函数的所有数据由相同的容器提取。

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

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

    如果需要在没有任何初始输入的情况下开始工作,长时间生存的 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 上的 mainsimple_handler.c 代码示例中的 方法。

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:greengrass:::runtime/function/executable。这是所有 Lambda 可执行文件的运行时环境。

注意

对于 role,您可以指定任何 Lambda 执行角色的 ARN。AWS IoT Greengrass 不使用该角色,但需要使用该参数以创建函数。有关 Lambda 执行角色的更多信息,请参阅 AWS Lambda 开发人员指南中的 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: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 可执行文件。要更新函数代码,您还必须使用 AWS Lambda API。

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