Yandex.Cloud中的物联网:Yandex IoT Core和Yandex Cloud Functions服务的安排方式



去年10月,举行了首届Yandex Yandex Scale云会议。它宣布推出了许多新服务,包括Yandex IoT Core,该服务使您可以与数百万IoT设备交换数据。

在本文中,我将讨论为何需要Yandex IoT Core及其工作方式,以及它如何与其他Yandex.Cloud服务进行交互。您将了解体系结构,组件交互的复杂性以及功能实现的功能-所有这些都将帮助您优化这些服务的使用。

首先,让我们回顾一下公共云和PaaS的主要优势-减少开发时间和成本,以及支持和基础架构成本,这也与IoT项目相关。但是,您可以在云中获得一些不太明显的有用功能。在使用设备时,尤其是在关键信息基础架构项目中,这种有效的缩放和容错能力是重要的方面。

有效的扩展是自由增加或减少设备数量而又不会遇到技术问题并在更改后看到系统成本可预测变化的能力。

容错是对服务的设计和部署的信心,即使在某些资源出现故障的情况下,也可以确保最高的性能。

现在让我们进入细节。

物联网脚本架构


首先,让我们看一下IoT脚本的整体架构。



其中可以分为两个主要部分:

  • 首先是将数据传输到存储设备以及将命令传输到设备。构建物联网系统时,无论您从事什么项目,都必须解决此任务。
  • 第二个是处理接收到的数据。一切都类似于基于数据集的分析和可视化的任何其他项目。您有一个包含初始信息数组的存储库,可以使用该信息库来实现您的任务。

第一部分在所有物联网系统中都大致相同:它是基于通用原理构建的,适合于适用于大多数物联网系统的通用场景。

尽管第二部分是建立在标准组件上的,但在执行功能方面几乎总是唯一的。同时,如果没有与硬件交互的高质量,容错和可扩展的系统,由于根本没有要分析的内容,因此体系结构分析部分的有效性几乎降低为零。

这就是Yandex.Cloud团队首先决定专注于构建便捷的服务生态系统的原因,该生态系统将快速,高效和可靠地将数据从设备传输到存储,反之亦然-向设备发送命令。



为了解决这些问题,我们正在研究Yandex IoT Core,Yandex Functions和云中数据存储服务的功能和集成:

  • Yandex IoT Core服务是具有多套有用功能的多租户故障安全可扩展MQTT代理。
  • Yandex Cloud Functions服务是有前途的无服务器方向的代表,它使您可以在安全,容错和自动可扩展的环境中将代码作为功能运行,而无需创建和维护虚拟机。
  • Yandex对象存储是大型数据阵列的有效存储,非常适合“历史”存档记录。
  • , , Yandex Managed Service for ClickHouse, «» . «» , , , .

如果数据存储和分析服务是已经写过很多篇的“通用”服务,那么Yandex IoT Core及其与Yandex Cloud Functions的交互通常会引起很多问题,特别是对于刚开始了解物联网和云技术的人们。并且由于这些服务提供了容错能力和与设备一起使用的扩展能力,因此我们将首先了解它们的内在功能。

Yandex IoT Core如何工作


Yandex IoT Core是一种专门的平台服务,用于云和运行MQTT协议的设备之间的双向数据交换。实际上,该协议已成为将数据传输到物联网的标准。它使用命名队列(主题)的概念,一方面可以写数据,另一方面可以通过订阅此队列的事件来异步接收数据。

Yandex IoT Core服务是多租户,这意味着所有用户都可以访问一个单一实体。也就是说,所有设备和所有用户都与同一服务实例进行交互。

一方面,这可以确保所有用户的工作均一性,另一方面,可以有效地扩展和容错,以便与数量不限的设备保持连接并在数量和速度上处理数量不限的数据。

因此,该服务必须同时具有冗余机制和灵活管理所使用资源的能力,以便响应负载变化。

另外,多租户需要共享MQTT主题访问权限的特殊逻辑。

让我们看看这是如何实现的。

像许多其他Yandex.Cloud服务一样,Yandex IoT Core在逻辑上分为两部分-控制平面和数据平面:



Data Plane负责MQTT协议下的操作逻辑,而Control Plane负责划定对某些主题的访问权限,并为此使用逻辑实体Registry and Device。



每个Yandex.Cloud用户可以拥有多个注册表,每个注册表都可以包含自己的设备子集。

提供对主题的访问,如下所示:



设备只能将数据发送到其事件主题和注册表事件主题:

$devices/<Device1 ID>/events
$registries/<Registry ID>/events

并仅订阅来自您的命令主题和注册表命令主题的消息:

$devices/<Device1 ID>/commands
$registries/<Registry ID>/commands

注册表可以将数据发送到设备命令的所有主题以及注册表命令的主题:

$devices/<Device1 ID>/commands
$devices/<Device2 ID>/commands
$registries/<Registry ID>/commands

并订阅来自设备事件所有主题和注册表事件主题的消息:

$devices/<Device1 ID>/events
$devices/<Device2 ID>/events
$registries/<Registry ID>/events

为了使用上述所有实体,Data Plane具有gRPC协议和REST协议,基于这些协议,可以通过Yandex.Cloud的GUI控制台和CLI命令行界面实现访问。

至于数据平面,它支持MQTT协议版本3.1.1。但是,有几个功能:

  1. 连接时,请确保使用TLS。
  2. 仅支持TCP连接。WebSocket尚不可用。
  3. 通过登录名和密码(其中登录名是设备或注册表ID,密码由用户设置)既可以使用授权,也可以使用证书。
  4. 不支持“保留”标志,当MQTT代理使用该标志来保存标有该标志的消息并在您下次订阅该主题时将其发送。
  5. 不支持持久会话,其中MQTT代理保存有关客户端(设备或注册表)的信息以促进重新连接。
  6. 使用订阅和发布,仅支持前两个服务级别:
    1. QoS0-最多一次。没有传递保证,但是没有重新传递相同的消息。
    2. QoS1-至少一次。可以保证传递,但是有可能再次收到相同的消息。

为了简化与Yandex IoT Core的连接,我们定期在GitHub上的存储库中添加适用于不同平台和语言的新示例,并在文档中描述脚本。

服务体系结构如下所示:服务的



业务逻辑包括四个部分:

  1. Device management — . Control Plane.
  2. MQTT Broker — MQTT-. Data Plane.
  3. Triggers — Yandex Cloud Functions. Data Plane.
  4. Shards — MQTT- . Data Plane.

与“外部世界”的所有交互都通过负载平衡器进行。此外,根据狗食原则,使用了Yandex Load Balancer,所有Yandex.Cloud用户都可以使用它。

业务逻辑的每个部分都由几组三个虚拟机组成-每个可用性区域一个(在方案A,B和C中)。虚拟机与所有Yandex.Cloud用户完全相同。当负载增加时,将在整个集合的帮助下进行扩展-在业务逻辑的一部分的框架内一次添加三台机器。这意味着,如果一组三台MQTT Broker计算机无法处理负载,那么将添加另一组三台MQTT Broker计算机,而业务逻辑其他部分的配置将保持不变。

而且只有Logbroker不可公开获得。它是一项用于对数据流进行有效的故障保护操作的服务。它基于Apache Kafka,但是它还有许多其他有用的功能:它实现了灾难恢复过程(包括在没有重复消息传递保证的情况下仅包含一次语义)和服务过程(例如跨中心复制,集群),并且还具有一种在流量订阅者之间进行统一非重复数据分布的机制-一种负载均衡器。

上面介绍了控制平面中的设备管理功能。但是有了数据平面,一切都变得有趣了。

MQTT Broker的每个实例都独立工作,对其他实例一无所知。代理将所有接收到的数据(从客户发布)发送到Logbroker,碎片和触发器从那里获取它们。代理实例之间发生同步是在分片中。分片了解所有MQTT客户端及其在MQTT代理实例之间的订阅分布(订阅),并确定将接收到的数据发送到何处。

例如,MQTT客户端A从代理A订阅了该主题,而MQTT客户端B从代理B订阅了相同的主题。如果MQTT客户端C将发布发布到同一主题,但发布到代理C,则分片从代理C和代理A到代理B,因此MQTT客户端A和MQTT客户端B都将接收数据。



业务逻辑的最后一部分,触发器(触发器),也接收从MQTT客户端接收的所有数据,如果用户配置了该数据,则将它们传递给Yandex Cloud Functions服务的触发器。

如您所见,Yandex IoT Core具有相当复杂的架构和工作逻辑,在本地安装上很难重复。这使他即使承受了三个可用性区域中的两个可用性区域的损失,也可以计算出无限数量的连接和无限的数据量。

而且,所有这些逻辑对用户都是“幕后”隐藏的,但是从外部看,一切看起来都很简单-就像您在使用单个MQTT经纪人一样。

触发器和Yandex云功能


Yandex Cloud Functions是Yandex.Cloud中所谓的“无服务器”(无服务器)服务的代表。此类服务的主要本质在于,用户无需花费时间来设置,部署和扩展环境以执行代码,而只是为他处理最有价值的事情-编写执行必要任务的代码本身。对于函数来说,这就是所谓的原子无状态代码,可以由某些事件触发。 ``原子''和``无状态''表示该代码应执行一些相对较小但不可分割的任务,而该代码不应使用任何变量来存储两次调用之间的值。

调用函数有几种方法:直接HTTP调用,计时器调用(cron)或事件订阅。与后者一样,该服务已经支持订阅消息队列(Yandex消息队列),对象存储服务生成的事件,以及(对于IoT场景最有价值)订阅Yandex IoT Core中的消息。

尽管您可以使用任何兼容MQTT的客户端使用Yandex IoT Core,但Yandex Cloud Functions是接收和处理数据的最理想,最方便的方法之一。原因很简单。可以在来自任何设备的每个传入消息上调用一个函数,并且这些函数将彼此并行执行(由于原子性和无状态方法),并且随着来自设备的传入消息数的更改,其调用次数自然会发生变化。因此,用户可以完全忽略建立基础结构的问题,而且,与相同的虚拟机不同,用户只为实际执行的工作付费。这将使您在低负载时节省大量资金,并随着增长而获得清晰可预测的成本。

在事件上(订阅事件)调用函数的机制称为触发器(Trigger)。该图的本质描述如下:



生成用于调用函数的事件服务将它们放入Logbroker中的队列中。对于Yandex IoT核心,数据平面触发器将执行此操作。此外,这些事件由预处理器处理,该预处理器正在数据库中寻找该事件的记录,以指示要调用的功能。如果找到了这样的条目,则预处理器会将有关函数调用的信息(函数ID和调用参数)放入Yandex Message Queue服务的队列中,然后由调用处理程序将其提取。反过来,处理程序将HTTP请求发送给Yandex Cloud Functions服务,以调用该函数。

同时,再次根据狗食的哲学,使用了对所有用户都可访问的Yandex Message Queue服务,并且调用这些函数的方式与其他用户可以调用其函数的方式完全相同。

我们来谈谈Yandex Message Queue。尽管与Logbroker一样,这是一个队列服务,但它们之间还是有很大的不同。处理来自队列的消息时,处理程序会通知队列它已完成,并且可以删除该消息。这是此类服务中重要的可靠性机制,但它使处理消息的逻辑变得复杂。

Yandex Message Queue允许您“并行化”队列中每个消息的处理。换句话说,当前正在处理的队列中的消息不会阻止另一个“线程”从队列中提取下一个事件进行处理的可能性。这称为消息级并发。

LogBroker对消息组进行操作,并且在处理整个组之前,不能拾取下一个组进行处理。这种方法在分区级别称为并发。

而正是Yandex Message Queue的使用,使您可以快速高效地并行处理大量请求,以针对特定服务的事件调用函数。

尽管触发器是一个独立的独立单元,但它们是Yandex Cloud Functions服务的一部分。我们只需要弄清楚函数的调用方式即可。



所有调用功能的请求(外部和内部)均落入负载平衡器,该负载平衡器将其分配到不同访问区域(AZ)中的路由器,每个区域中部署了几部分。收到请求后,路由器首先进入身份和访问管理器(IAM)服务,以确保请求源具有调用此功能的权限。然后,他转向调度程序,并询问要在哪个工作程序上运行该功能。 Worker是具有隔离功能的自定义运行时的虚拟机。此外,路由器已经从调度器接收了要在其上执行功能的工作人员的地址,该路由器向该工作人员发送命令以使用某些参数启动该功能。

工人来自哪里?这是所有无服务器魔术发生的地方。调度程序分析负载(功能的数量和持续时间),并在特定的运行时管理(启动和停止)虚拟机。现在支持NodeJS和Python。其中一个参数非常重要-启动功能的速度。服务开发团队做了出色的工作,现在虚拟机最多可以启动250毫秒,同时使用最安全的环境将功能彼此隔离-QEMU虚拟化,该虚拟机运行Yandex.Cloud的全部功能。同时,如果传入请求已经有工作人员,则该功能几乎立即启动。
而且,按照相同的“狗粮”方法,负载均衡器使用所有用户均可访问的公共服务,而工作程序,调度程序和路由器是与所有用户相同的普通虚拟机。

因此,服务的容错能力是在负载均衡器级别和关键系统组件(路由器和调度程序)的冗余级别实现的,并且由于部署或减少了工作人员的数量而发生了扩展。此外,每个可访问区域都独立工作,这使得即使在三个区域中的两个区域也不会丢失。

有用的链接


最后,我想提供一些链接,使您可以更详细地研究服务:


All Articles