news 2026/9/15 15:51:21

Azure Functions 输出绑定深入探究:在 IoT-For-Beginners 交通项目中用 Blob 存储输出绑定保存 GPS 数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Azure Functions 输出绑定深入探究:在 IoT-For-Beginners 交通项目中用 Blob 存储输出绑定保存 GPS 数据

Azure Functions 输出绑定深入探究:在 IoT-For-Beginners 交通项目中用 Blob 存储输出绑定保存 GPS 数据

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

本篇文章是 IoT-For-Beginners 课程3-transport/lessons/2-store-location-data(存储位置数据)一课课后作业(assignment.md)的深入展开。该作业的核心任务是:理解 Azure Functions 的触发器和绑定机制,掌握通过function.json配置Blob 存储输出绑定(Blob storage output binding),让函数代码只需从main函数返回 blob 即可自动写入 Azure Blob 存储。读完本文,你将掌握函数绑定(trigger / input / output)的基础概念、function.json的配置语法、输出绑定与 Python SDK 两种写入存储方案的取舍,并能对照本仓库内的完整代码完成自己的绑定配置实验。

一、作业背景:为什么需要函数绑定

在上一课中,GPS 传感器采集到的经纬度数据被发送到 Azure IoT Hub。为了在下一课中把这些数据绘制到地图上,这些遥测事件需要被服务端代码接住并持久化——这正是本课 "warm path(温路径)" 数据流的一部分:数据到达云端后先落盘存储,供短期报告和分析使用。

在 3-transport/lessons/2-store-location-data/README.md 中,官方给出了两条连接存储的路线:

  1. 在函数代码内部,用 Blob 存储 Python SDK 连接存储账户并把数据写成 blob;
  2. 使用输出函数绑定(output function binding),把函数的返回值绑定到 Blob 存储,由运行时自动保存。

本课正文采用了第 1 种(Python SDK)方案;而本次作业要求你自行研究第 2 种方案——读懂 Azure Functions 官方文档中关于 "Triggers and Bindings" 与 "Blob storage output binding" 的说明,弄清楚如何配置输出绑定,并把它实际跑通。这是一种典型的 "课堂给方案、作业考原理" 的设计:能理解绑定的声明式配置,才真正理解 Azure Functions 的运行模型。

二、什么是 Azure Functions 的触发器和绑定

Azure Functions 的绑定模型把"函数与外部服务的数据交互"从代码中抽离出来,声明式地放在配置文件里。绑定分为三类:

  • Trigger(触发器):定义函数被调用的时机,是函数的入口事件源。一个函数有且只有一个触发器。
  • Input binding(输入绑定):为函数提供额外的只读数据输入。
  • Output binding(输出绑定):把函数的结果(如返回值)自动写入目标服务,无需在代码里手写连接逻辑。

在本仓库的函数项目中,main函数的入口正是一个 Event Hub 触发器,声明在 function.json 中:

{ "scriptFile": "__init__.py", "bindings": [ { "type": "eventHubTrigger", "name": "events", "direction": "in", "eventHubName": "samples-workitems", "connection": "IOT_HUB_CONNECTION_STRING", "cardinality": "many", "consumerGroup": "$Default", "dataType": "binary" } ] }

字段含义拆解:

字段作用
type绑定类型,这里是eventHubTrigger(Event Hub 兼容端点触发器)
name绑定在代码中的参数名,events对应main(events: List[func.EventHubEvent])的入参
direction数据方向,in表示输入/触发器
eventHubNameEvent Hub 名称(示例值为占位符samples-workitems
connection存放连接字符串的环境变量名,指向local.settings.json或云上 Application Settings 中的IOT_HUB_CONNECTION_STRING
cardinalitymany表示批量接收事件(对应List[func.EventHubEvent]),one表示单条
consumerGroup消费组,默认$Default
dataType数据类型,binary表示以二进制传入

关键点在于:触发器只负责"把事件送进函数",事件落盘存储则需要在bindings数组中追加一个方向为out的绑定条目。这正是作业要求你研究的内容。

三、function.json中声明 Blob 存储输出绑定

Azure Functions 的绑定配置遵循统一模型,输出绑定与输入绑定同处一个bindings数组,只需满足三点:

  1. type设为 Blob 存储相关类型(对 Python v2 之前的 v1/v2 模型为blob);
  2. direction设为out
  3. name与代码中main函数的参数名一致。

一个典型的 Blob 输出绑定条目如下(结合本作业任务与 官方输出绑定文档 的说明整理,供你对照自己的实现):

{ "type": "blob", "name": "outputBlob", "direction": "out", "path": "gps-data/{deviceId}/{rand-guid}.json", "connection": "STORAGE_CONNECTION_STRING" }
  • path:blob 的容器与文件名模板。这里的{deviceId}来自函数签名中的绑定表达式(binding expression),{rand-guid}是系统提供的随机 GUID——无需自己用uuid生成文件名,运行时自动展开。
  • connection:存储账户连接字符串所在的环境变量名(本仓库中即STORAGE_CONNECTION_STRING,见 local.settings.json)。

配置完成后,在__init__.pymain函数签名中加入同名参数,函数return一个字节串或字符串即可自动写入 blob:

import azure.functions as func def main(events: func.EventHubEvent, outputBlob: func.Out[str]): body = events.get_body().decode('utf-8') # 把结果通过输出绑定写回 blob 存储 outputBlob.set(json.dumps({"gps": json.loads(body)["gps"]}))

如果采用"返回值绑定"的写法(不使用func.Out参数而是直接 return),则函数返回的内容会按path写入存储;返回None时不会产生任何写入。这正是作业描述中"通过从main函数返回 blob 来保存到 blob 存储"的含义。

四、两种写入方案在仓库中的实际对照

为了帮助你完成作业,可以对比本仓库已经实现好的SDK 方案(课堂正文路线),它就是你实现输出绑定方案时的参照物。

4.1 SDK 方案:手写连接与上传

仓库的 iot-hub-trigger/init.py 完整实现了"用 Python SDK 写 blob":

def get_or_create_container(name): connection_str = os.environ['STORAGE_CONNECTION_STRING'] blob_service_client = BlobServiceClient.from_connection_string(connection_str) for container in blob_service_client.list_containers(): if container.name == name: return blob_service_client.get_container_client(container.name) return blob_service_client.create_container(name, public_access=PublicAccess.Container) def main(events: List[func.EventHubEvent]): for event in events: logging.info('Python EventHub trigger processed an event: %s', event.get_body().decode('utf-8')) device_id = event.iothub_metadata['connection-device-id'] blob_name = f'{device_id}/{str(uuid.uuid1())}.json' container_client = get_or_create_container('gps-data') blob = container_client.get_blob_client(blob_name) event_body = json.loads(event.get_body().decode('utf-8')) blob_body = { 'device_id' : device_id, 'timestamp' : event.iothub_metadata['enqueuedtime'], 'gps': event_body['gps'] } logging.info(f'Writing blob to {blob_name} - {blob_body}') blob.upload_blob(json.dumps(blob_body).encode('utf-8'))

这套代码里能看到 SDK 方案的全部细节:

  • 连接串os.environ['STORAGE_CONNECTION_STRING']读取,本地开发时由 local.settings.json 注入,云端部署后由 Application Settings 注入;
  • 容器不存在时自动创建get_or_create_container先遍历list_containers(),找不到再create_container(..., public_access=PublicAccess.Container)。给容器开放公共访问权限,是为了下一课在地图上可视化 GPS 数据时可以直接查询;
  • blob 名按设备分文件夹f'{device_id}/{str(uuid.uuid1())}.json',例如gps-sensor/a9487ac2-b9cf-11eb-b5cd-1e00621e3648.json
  • blob 内容结构{"device_id": ..., "timestamp": <入队时间>, "gps": {"lat": ..., "lon": ...}}。特别地,时间戳取event.iothub_metadata['enqueuedtime'](消息入队时间)而非当前时间——如果 Functions 应用未运行,消息可能在 Hub 上滞留一段时间,用入队时间才能还原真实发送时刻。

4.2 输出绑定方案:声明式自动写入

对照之下,输出绑定方案的目标是删掉上面这段样板代码:不再 importBlobServiceClient、不再管理连接串、不再手工upload_blob,只需在function.json里加一个out绑定,并在函数签名/返回值中暴露该绑定。两者的能力对比如下:

维度Python SDK 方案(本课正文)输出绑定方案(本次作业)
连接管理代码中从环境变量读取并创建客户端运行时根据connection字段自动处理
容器创建需手写get_or_create_container需预先创建容器(或依赖绑定路径)
blob 命名代码中用uuid拼路径绑定path模板 +{rand-guid}表达式
代码侵入高,需要存储相关 import 与异常处理低,只关心业务数据组装
灵活性高,可自由控制容器/权限/批量逻辑较低,按声明模板写入

五、本地开发环境的配套配置

无论走哪条路线,本地开发都依赖同一个配置骨架,值得一并掌握:

  • local.settings.json:本地密钥与运行时配置,FUNCTIONS_WORKER_RUNTIMEpythonAzureWebJobsStorage使用UseDevelopmentStorage=true(指向 Azurite 本地存储模拟器),IOT_HUB_CONNECTION_STRINGSTORAGE_CONNECTION_STRING分别供给触发器和存储绑定使用;
  • host.json:Functions 宿主配置,版本2.0,并通过extensionBundle引入Microsoft.Azure.Functions.ExtensionBundle[2.*, 3.0.0)),绑定扩展无需单独安装 NuGet 包——这正是绑定声明式配置得以简化运行成本的关键;
  • requirements.txt:Python 依赖清单,注意注释明确提醒不要包含azure-functions-worker(会与 Functions 平台冲突),只需azure-functionsazure-storage-blob

六、作业验收标准与自查清单

作业 assignment.md 给出的评估标准(Rubric)是一张单维度表格,围绕"是否成功配置 Blob 存储输出绑定"分级:

标准优秀(Exemplary)合格(Adequate)需改进(Needs Improvement)
配置 Blob 存储输出绑定能配置输出绑定、返回 blob,且 blob 成功写入存储能配置输出绑定、或能返回 blob,但未能成功写入存储完全无法配置输出绑定

对照此标准,完成作业时可按下述步骤自查:

  1. 确认绑定声明正确function.jsonbindings数组中包含type: "blob"direction: "out"的条目,且path指向gps-data容器;
  2. 确认连接串生效local.settings.jsonSTORAGE_CONNECTION_STRING的值来自az storage account show-connection-string --output table --name <storage_name>命令的输出;函数签名与function.jsonname字段一致;
  3. 确认返回值被写入:运行 Functions 应用的同时让虚拟设备(code/virtual-device/gps-sensor/app.py)持续发送 GPS 遥测(JSON 格式为{"gps": {"lat": ..., "lon": ...}}),然后用az storage blob list --container-name gps-data --output table --account-name <storage_name> --account-key <key1>检查容器中是否出现新 blob,并用az storage blob download下载校验内容;
  4. 注意调试陷阱:运行 Functions 应用时不要同时运行az iot hub monitor-events抢占 Event Hub 消费;输出绑定模式下若返回None则不会写入任何 blob,这是最常见的"配置正确却无数据"原因。

七、结语

本次作业的价值在于把"数据如何从 IoT Hub 流到 Blob 存储"这件事从"调用代码"提升到"声明配置"的认知层次。function.json中的每个绑定条目都是一种契约:触发器声明数据从哪里来,输出绑定声明数据到哪里去。你在 3-transport/lessons/2-store-location-data/README.md 中已经看到了 SDK 路线的完整实现,而作业要你独立走通输出绑定路线——两条路线殊途同归,最终都服务于下一课"在地图上可视化车辆轨迹"的 warm path 数据流。

提示:本作业涉及的微软官方文档(Azure Functions 触发器与绑定概念、Blob 存储绑定概览、Blob 存储输出绑定)建议直接访问微软文档站点阅读,注意其中的 Python 版本标签页与绑定属性参考。本文档源自课程翻译版本,作业原文以 3-transport/lessons/2-store-location-data/assignment.md 为准。

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 15:50:10

Loop 窗口管理快速指南:3分钟把窗口对齐交给一次击键

Loop 窗口管理快速指南&#xff1a;3分钟把窗口对齐交给一次击键 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 第三块外接屏上&#xff0c;窗口永远差几个像素没对齐&#xff0c;两栏布局拖了十分钟还…

作者头像 李华
网站建设 2026/9/15 15:49:18

如何用 deck.gl 的 FirstPersonView 配置第一人称相机视角

如何用 deck.gl 的 FirstPersonView 配置第一人称相机视角 【免费下载链接】deck.gl WebGL2 powered visualization framework 项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl FirstPersonView 是 deck.gl 提供的第一人称视角 View 类&#xff1a;相机被放置…

作者头像 李华
网站建设 2026/9/15 15:48:17

AMFI绕过全解析:vphone-cli 如何破解 iOS 代码签名信任机制

AMFI绕过全解析&#xff1a;vphone-cli 如何破解 iOS 代码签名信任机制 【免费下载链接】vphone-cli 项目地址: https://gitcode.com/GitHub_Trending/vp/vphone-cli AMFI 绕过是 vphone-cli 能在 Mac 上启动虚拟 iPhone 并运行未签名代码的核心。本文带你从 iOS 代码签…

作者头像 李华