MQTT 指南

MQTT 指南 - 定义、用例、应用和资源

阅读电子书

MQTT 是一种在物联网行业中迅速普及的协议。这是因为与大多数应用程序相比,物联网应用程序工作负载具有独特的要求。像 HTTP 这样更常见的网络协议对于网络连接可能断断续续、硬件处理能力可能较低且带宽受限的物联网环境来说并不理想。虽然物联网通信有多种选择,但 MQTT 已成为默认的网络协议,因为它提供了许多优势,这些优势将在本网页中深入介绍。

什么是 MQTT?

MQTT 是一种机器对机器 (M2M)/物联网通信协议,设计为轻量级的发布/订阅消息传递工具。MQTT 适用于需要小资源占用空间和/或网络带宽受限的连接。MQTT 由 IBM 的 Andy Stanford-Clark 博士和 Arcom 的 Arlen Nipper 于 1999 年创建。当时,IBM 正在与一家石油和天然气公司合作,该公司需要从偏远地区的输油管道中提取数据,这需要一种新的协议来满足这些要求。MQTT 由此诞生。

MQTT 在 IBM 内部使用,直到他们在 2010 年发布了 MQTT 3.1 规范,允许其他人创建自己的 MQTT 实现。开发人员很快意识到 MQTT 对于物联网相关用例的价值,并且应用迅速普及,创建了许多开源代理和客户端库。2013 年,IBM 将 MQTT 提交给 OASIS 以进行维护和标准化。

MQTT 用例

MQTT 是一种通用的网络协议,非常适合任何网络可能不可靠、您希望最大限度地减少带宽消耗、拥有低功耗硬件,或者您的架构中有许多客户端设备需要在近乎实时的访问相同数据的情况。

消费者物联网

MQTT 用于许多消费者物联网设备之间的通信。这可能包括从旨在自动化事物并使您的家更高效的智能家居类型设备到各种设备。

工业物联网

MQTT 最初是为石油和天然气行业的工业用途而设计的,并且由于它比竞争网络协议具有许多优势,因此迅速扩展到制造等其他领域。MQTT 通过允许公司收集更多数据并更快地对这些数据采取行动,帮助公司提高效率。

物流

MQTT 非常适合实时监控世界各地移动的资产。即使互联网连接丢失,MQTT 也旨在确保一旦重新获得连接,数据就能得到交付。在一个供应链日益复杂的世界中,MQTT 变得越来越重要。

移动应用程序开发

您可能熟悉的、使用 MQTT 的一个应用程序是 Facebook Messenger。Facebook Messenger 团队之所以选择 MQTT 而不是 HTTP,是因为移动应用程序与物联网工作负载非常相似,尤其是对于群聊,MQTT 的发布/订阅架构非常自然,并且可以轻松添加成员,每个群聊都是客户端可以订阅的自己的主题。

对于一般的移动应用程序,MQTT 非常理想,因为它允许持久连接以接收新消息,而不会消耗大量带宽或耗尽手机电池。如果您正在构建任何需要频繁网络通信的移动应用程序,MQTT 可能是可靠的选择。

MQTT 如何工作

MQTT 使用发布/订阅消息模式,这意味着客户端设备连接到充当这些设备之间中间人的代理。连接到代理的设备可以发布消息,这些消息将通过代理转发到其他连接的设备。每条消息都必须有一个主题,并且代理只会将消息传递给明确订阅了主题的设备。

how-MQTT-works-1024x503

使用 MQTT,任何连接的客户端设备都可以在连接到 MQTT 代理后发送或接收消息。每个设备还可以选择仅发布消息而不订阅主题,或者仅订阅主题而从不发布任何消息。

以智能家居为例,房子的每个房间都可以指定为一个主题。让每个设备接收和处理与其不相关的消息是没有意义且效率低下的。因此,MQTT 允许开发人员定义主题,以便每个设备只接收它需要的数据。

MQTT 的优势和劣势

没有完美的网络协议,MQTT 根据定义必须做出一些权衡才能针对物联网用例进行优化。在本节中,您将了解有关 MQTT 优势和劣势的更多详细信息,以便您可以确定是否适合在您的项目中使用它。

MQTT 优势

MQTT 的主要优势是

  • 效率
  • 可靠性
  • 灵活性

MQTT 经过优化,可在每条发送的消息中使用尽可能少的数据和能量。MQTT 能够重用与代理的连接来发送多条消息,与像 HTTP 这样的协议相比,这节省了资源开销。您可以将 HTTP 想象成给某人打电话,然后在您谈论的每个句子后挂断电话,然后再打电话给他们继续对话,这显然不如正常的电话通话有效。结果是,一旦 MQTT 连接建立,与使用 HTTP 相比,通过 MQTT 发送的每条消息使用的带宽减少了 10 倍,这是基于 Google 执行的测试。

MQTT-vs-HTTP

来源

MQTT 在消息大小方面也更有效率。例如,MQTT 的标头是 2 字节的数据,而 HTTP 标头对于 GET 请求至少为 16 字节,并且使用 HTTP,该标头必须在每条消息上发送,而 MQTT 仅在创建与代理的连接时发送标头。发布/订阅架构也很高效,因为它消除了每个设备在特定时间间隔通过轮询检查新消息的需要。相反,设备等待接收由代理直接传递的消息,这不仅确保它们更快地获得新消息,而且效率更高。

MQTT 因其发布/订阅架构而可靠,该架构允许代理缓冲消息并将消息保存到订阅设备再次连接。MQTT 还为消息提供服务质量级别,以确保关键数据的交付,或通过允许丢弃一些非关键任务数据来节省资源。

灵活性是 MQTT 的另一个主要优势。如上所述,用户可以根据情况控制消息的服务级别要求。MQTT 在消息包含的内容方面也是数据不可知的,这意味着消息有效负载可以包含二进制数据、ASCII 文本或任何其他数据类型。MQTT 的解耦发布/订阅架构意味着可以通过添加更多代理来轻松扩展它,以处理更多设备,因为设备数量增加或消息频率增加。

MQTT 劣势

MQTT 的主要劣势是

  • 延迟
  • 架构复杂性
  • 低功耗设备上的资源需求
  • 安全性

对于需要极低延迟的用例,MQTT 可能会成为问题,因为消息必须通过 MQTT 代理才能到达目的地,而不是能够直接从一个设备到另一个设备,这会造成延迟。

MQTT 代理的管理也可能成为架构复杂性的来源,因为代理是必须管理和监控以确保整个系统正常运行的另一项服务。对于较大的工作负载,这可能需要多个代理实例,这需要负载均衡以确保消息在它们之间均匀分配。

虽然 MQTT 是一种轻量级协议,但它提供的功能数量确实使其比某些替代方案更消耗资源。通常,这不会成为问题,除非对于最低功耗的硬件,但如果您正在使用这种类型的硬件,这可能是相关的。

安全性可以被认为是 MQTT 的另一个普遍劣势。默认情况下,MQTT 不提供任何安全功能 — 任何形式的加密都需要使用 MQTT 构建在其之上的底层 TCP 协议来实现。虽然 SSL/TLS 是安全性的绝佳选择,但这仍然是必须管理和实施以确保您的数据安全的事情。最新版本的 MQTT,MQTT v5 也添加了一些额外的安全功能,稍后将介绍这些功能。

MQTT 的关键概念和特性

在本节中,您将了解一些关键概念,如果您想使用 MQTT,您需要了解这些概念。您还将了解 MQTT 提供的一些基本功能。

MQTT 代理

MQTT 代理通过在连接的设备之间传递消息来工作。每个设备不需要尝试相互通信(这将极其复杂且资源密集),每个设备只需要创建与代理的单个连接,就可以从任何其他设备接收数据。

MQTT 代理可以处理数百万个连接的 MQTT 客户端,并提供许多将在本节后面介绍的功能。代理使这些功能成为可能,这也是 MQTT 在物联网开发人员中如此受欢迎的原因。

MQTT 客户端

MQTT 客户端只是任何运行 MQTT 客户端软件的设备,该软件允许它连接到 MQTT 代理。MQTT 客户端可以向代理发布消息,也可以订阅主题以接收消息。MQTT 客户端是任何能够运行 MQTT 客户端库实现并连接到 MQTT 代理的东西。

MQTT 协议详情

MQTT 的核心是构建在 TCP/IP 网络堆栈之上的。虽然与 UDP 相比,这稍微降低了性能和轻量级,但 TCP 允许保证交付,这对于许多物联网用例至关重要。使用 TCP 的另一个好处是 MQTT 可以使用 SSL/TLS 加密数据。

主题

主题是 MQTT 组织发送到代理的消息的关键方式。每条发送的消息都需要定义一个主题,连接的设备可以订阅主题以在发送消息时接收消息。主题是使用正斜杠分隔的 UTF-8 字符串。这是一个基本 MQTT 主题的示例

top/middle/bottom

这些消息可以是任何内容,但理想情况下,您应该具有一些基本结构,以便随着应用程序随时间推移而增长以及添加更多主题,您的主题层次结构逻辑清晰且易于开发人员理解。主题不需要在发布消息或客户端订阅主题之前预先定义,您可以动态添加新主题,而无需担心。

以下是一些示例,说明如果您正在使用智能家居,则可以如何构建主题。

  • 地下室的湿度数据 - home/basement/mainroom/humidity
  • 客厅的温度数据 - home/mainfloor/livingroom/temperature
  • 卧室中特定设备的消息 - home/mainfloor/bedroom/device

除了上面主题这样的基本静态文本字符串之外,MQTT 还通过在斜杠之间使用 + 来支持动态主题。加号仅为您提供单级通配符匹配。如果您想要多级通配符支持,您可以使用井号,主题将匹配井号后的任何内容。例如,如果您想订阅智能家居生成的所有消息,您可以使用以下主题

home/#

这些通配符运算符非常有用,但应谨慎使用 — 在不需要时过度使用通配符会导致代理性能下降,因为它正在使用资源向不需要消息的设备发送消息。始终确保确定设备是否需要订阅 MQTT 主题 — 如果不需要,您将浪费带宽和处理能力来传递客户端不需要的 MQTT 消息。

会话

MQTT 会话被认为是客户端设备请求连接到 MQTT 代理到连接中断之间发生的一切。基于此,会话可能只是初始连接请求失败,或者可能是持久会话,客户端发布和接收了许多消息。

会话很重要,因为它们将具有关联状态,具体取决于所涉及消息的服务质量 (QoS) 级别设置。代理需要能够确定某些客户端设备是否已交付它们需要的消息,并且客户端需要在某些情况下响应以确认消息也已交付。

消息过期

MQTT 允许客户端为发布的消息设置过期间隔。间隔以秒为单位设置,并告知代理在删除消息之前存储消息多长时间。如果消息在客户端未连接时过期,则客户端将不会收到该消息。

保持活动功能

MQTT 提供了一种通过设置间隔以确认连接来确保代理和客户端之间已建立的连接仍然存活的方法。这被称为保持活动功能,频率可以由开发人员使用 MQTT 定义。如果在设定的间隔内,客户端未从代理发送或接收消息,则代理将 ping 客户端并期望得到响应。如果客户端没有响应,代理会将设备注册为断开连接。

保留消息

保留消息只是已标记的普通 MQTT 消息,因此它们由代理存储。通过使用保留消息,任何订阅主题的客户端都将收到最新的保留消息,以便客户端可以获得最新更新,而不是等待消息发送。

服务质量

服务质量 (QoS) 是 MQTT 如何控制消息交付保证的方式。MQTT QoS 本质上是消息的发送者和接收者之间就如何定义将消息视为“已交付”的要求达成的协议。在 MQTT 的情况下,有三个可用的服务质量级别

  • 最多一次 (0) - 最低的 QoS 级别,被认为是“尽力而为”的交付。不保证消息将到达订阅的客户端,并且不向发布设备发送任何确认。代理只是确认订阅的客户端设备已连接,然后将消息发送给它。
  • 至少一次 (1) - QoS 级别 1 确实保证消息的交付,但可能会导致消息被发送甚至交付多次。如果您不考虑应用程序中的这种情况,则对同一消息执行多个副本可能会导致问题。
  • 恰好一次 (2) - QoS 级别 2 是 MQTT 提供的最高服务级别。它不仅保证交付给订阅的客户端,而且确保它们只接收一次消息。MQTT 通过需要 4 部分握手来做到这一点,首先确认客户端收到了消息,然后使用标志进行另一个请求和响应,以确保没有收到重复的消息。

在消息传递过程中,将消息传递到目的地涉及两个部分。首先,消息由客户端创建和发布并发送到 MQTT 代理,然后代理需要将该消息传递给订阅的客户端。

QoS 是 MQTT 提供的最重要的功能之一,因为它允许开发人员根据其数据的重要性设置某些保证。这意味着即使在不可靠的网络上,MQTT 也可以依靠交付数据。同时,它为开发人员提供了灵活性;如果某些数据不重要,MQTT 可以让这些消息丢失,并且在某些情况下不会浪费带宽。

遗嘱

遗嘱和遗言是 MQTT 提供的一项功能,允许客户端指定一条消息,当客户端由于计划外的错误而结束连接时,该消息将发送给其他客户端设备。当客户端设备连接到 MQTT 代理时,遗嘱和遗言会被发送并存储在代理上。当代理检测到客户端在没有给出用于正常断开连接的标准 DISCONNECT 消息的情况下断开连接时,将发送该消息。

MQTT 版本 5 功能

虽然大多数 MQTT 部署仍在使用 MQTT 3.1.1,但 MQTT 版本 5 现已推出,并具有许多强大的新功能。大多数新项目将使用 MQTT 5,随着时间的推移,现有项目也将升级到 MQTT 版本 5。以下是 MQTT 版本 5 提供的一些最佳新功能

  • 原因代码 - MQTT 版本 5 中的原因代码允许在 MQTT 代理和客户端之间发生某些事件时,向 MQTT 客户端发送更多信息。例如,可以发送自定义原因代码来确认某些服务质量级别、连接失败、不同错误、无效主题、速率限制等等。
  • 断开连接消息 - MQTT v5 允许 MQTT 代理向客户端设备发送消息,说明连接关闭的原因,以便设备可以根据断开连接的原因采取措施。
  • 用户属性 - 可以将键值对的集合附加到消息,以提供额外的数​​据或上下文。
  • 服务器重定向 - 当客户端尝试连接到代理时,它可以被重定向到不同的 MQTT 代理。如果当前代理的连接数超过某个阈值,则可以使用此功能通过将设备发送到新的代理来实现负载均衡。
  • 主题别名 - 主题别名是从 MQTT-SN 中提取的功能,通过允许将长主题名称映射到较短的替代别名来帮助节省带宽,从而减小消息大小。
  • 请求/响应模式支持 - MQTT v5 使开发人员能够模拟更传统的请求/响应模式,以用于比 MQTT 的标准发布/订阅模型更适用的用例。对于这些情况,MQTT v5 添加了向消息添加响应主题的功能,客户端可以订阅这些主题,并且消息将被视为更标准的请求/响应消息,尽管由于 MQTT 的底层发布/订阅架构,它仍然是异步的。此功能仅仅是对顶层的抽象,旨在使开发人员更容易创建这些类型的请求,而无需额外的工作。
  • 共享订阅 - 共享订阅基本上是一种客户端负载均衡的形式,其中客户端设备可以全部订阅同一主题,并且消息将仅发送到单个设备,而不是将同一消息发送到每个设备。
  • 保留消息控制 - MQTT v5 使开发人员可以更好地控制如何处理保留消息,以应对诸如客户端首次订阅还是重新连接时是否应将保留消息发送到设备的情况。

MQTT 安全性

安全是任何类型的软件都面临的挑战,但物联网应用程序带来了另一层次的安全挑战。由于物联网设备在计算和内存资源方面通常受到限制,因此开发人员必须权衡他们可以使用的安全工具(如加密算法)。另一个挑战是有效地处理现场设备的更新。如果无法远程访问设备,软件更新将变得更加昂贵并且频率会降低。

在应用层,可以将 MQTT 设置为需要基本的用户名和密码进行身份验证。不同的 MQTT 代理实现也可能提供额外的安全功能。由于 MQTT 构建在 TCP 之上,因此 MQTT 还提供了使用 SSL/TLS 的传输层级安全选项来加密 MQTT 消息数据。在网络层,开发人员还可以选择尝试物理保护硬件设备和网络组件,以及使用虚拟专用网络 (VPN) 进行客户端和代理之间的通信。

MQTT 资源和工具

在本节中,您将了解更广泛的 MQTT 生态系统以及可供希望将 MQTT 用于其应用程序的开发人员使用的一些工具。

MQTT 代理实现

有许多可用的开源和商业 MQTT 代理可供您开始使用 MQTT。以下是一些最受欢迎的选择。

Mosquitto Mosquitto 是最受欢迎的开源 MQTT 代理,并受到 Eclipse 基金会的支持。如果您不希望依赖于由供应商支持的代理实现,而该供应商由于提供其开源实现的商业替代方案而存在某种利益冲突,那么 Mosquitto 可能是最好的 MQTT 代理。

EMQX EMQX 是由 EMQ 公司创建的开源、云原生 MQTT 代理,EMQ 公司是与 IBM 一起成为 OASIS 的创始赞助商。EMQX 是第一个完全支持 MQTT 版本 5 功能的 MQTT 代理,EMQ 声称 EMQX 代理集群可以处理 1 亿个订阅者。

EMQ 还提供了许多其他有用的开源工具来处理 MQTT,例如 NanoMQ 和 Neuron,它们与 EMQX 协同工作,以帮助连接从边缘到云的物联网设备。

HiveMQ HiveMQ 是 MQTT 生态系统中另一个受欢迎的供应商。HiveMQ 提供支持 MQTT 版本 3 和 5 的开源代理。HiveMQ 还提供托管的 MQTT 代理,可用于扩展您的 MQTT 应用程序,并与 InfluxDB 良好集成。

MQTT 客户端库

有许多客户端库可用于以您选择的语言处理 MQTT。大多数供应商都提供自己的实现,但最受欢迎的客户端库是 Eclipse 基金会支持的 Paho MQTT 库

MQTT 的数据存储

MQTT 消息通常包含时间序列数据。这些数据从可能大量设备中快速流式传输。对于许多与物联网相关的工作负载,这些数据还需要能够在摄取后不久进行分析——对于需要近乎实时访问数据的监控情况,长时间的延迟是不可接受的。时间序列数据库(如 InfluxDB)专为这些要求而设计,并在写入和查询数据方面提供了许多纯粹的性能优势,以及由于许多开箱即用的内置功能(如下采样和时间序列数据所需的常见分析和预测功能)而带来的更快的开发时间等优势。

MQTT Sparkplug

MQTT Sparkplug 是为定义网络边缘网关和设备应如何通信的更标准化架构而创建的规范。虽然 Sparkplug 可以用于任何 MQTT 应用程序,但它针对涉及 SCADA 和传统 工业物联网 用例的系统进行了优化,并使这些系统与 MQTT 更加互操作。MQTT Sparkplug 由 Eclipse 创建,Eclipse 也是维护 Paho MQTT 客户端库的组织。Sparkplug 规范有三个主要组成部分

  • MQTT 主题命名空间 - 默认情况下,MQTT 不强制执行任何必需的主题约定或命名空间,Sparkplug 旨在为构建主题创建更标准化的约定
  • MQTT 状态管理 - Sparkplug 定义了许多新的消息类型,这些消息类型可以帮助进行状态管理,例如处理连接状态和处理指标数据。这些消息类型包括用于网络边缘 MQTT 节点和设备本身的连接和断开连接的消息。还有用于节点与设备消息的消息类型,以及定义消息重要程度的能力。
  • MQTT 有效负载定义 - Sparkplug 具有基于 Google Protobufs 的消息编码。这减少了带宽使用,并且还可以更轻松地与用于工业物联网应用程序的其他协议(如 Modbus)集成。Protobufs 还允许为有效负载创建数据模型,以定义历史数据、文件数据、数据集、通过模板定义的复杂数据、指标的元数据和指标别名。

Node-RED

Node-RED 是一个开源低代码框架,用于创建事件驱动的应用程序。它提供了一个可视化构建器来集成硬件和软件组件,并且由 IBM 为物联网项目设计。Node-RED 是快速创建基于 MQTT 的应用程序(用于原型设计和生产)的绝佳选择。

MQTT 常见问题解答

MQTT 代表什么?

MQTT 最初代表 MQ 遥测传输 (MQ Telemetry Transport),但 MQTT 不再是首字母缩略词,而只是协议的名称。

什么是 MQTT-SN?

MQTT-SN 代表传感器网络 MQTT (MQTT for Sensor Networks)。MQTT-SN 专为在无线网络上工作而设计,并针对通常通过无线网络通信的低功耗传感器进行了优化。MQTT-SN 与标准 MQTT 之间的主要区别在于 MQTT-SN 不需要 TCP,并且可以使用 Zigbee 或 Thread 等串行通信协议。其他一些区别是 MQTT-SN 使用主题 ID 而不是主题名称,允许预定义主题,并且具有用于休眠客户端设备的保持活动功能。

MQTT 与 AMQP

MQTT 和 AMQP 都是用于跨系统发送和接收消息的异步消息协议。主要区别在于 MQTT 针对物联网用例进行了高度优化,因此是一个更小、更简单的协议。AMQP 旨在涵盖更通用的用例,因此具有更多可用功能,但也更复杂且效率较低。

在功能方面,AMQP 可以被认为在安全选项方面胜出,因为它开箱即用地包含 SASL 等功能,而使用 MQTT 则需要您自己添加。AMQP 还提供了扩展协议的能力,同时保持向后兼容性,而 MQTT 更改则需要版本更新。AMQP 提供了 MQTT 的发布/订阅模式之外的几种消息传递模式。与 MQTT 相比,MQTT 的主要优点是它更轻量级,因此更适合电池和资源受限的硬件。MQTT 还消耗更少的带宽,并且在不可靠的网络上效果更好。简而言之,MQTT 和 AMQP 之间的主要区别在于 AMQP 是一种通用消息传递协议,而 MQTT 从一开始就被设计为一种专门协议,以适应特定的用例。您应该使用 MQTT 还是 AMQP 将取决于哪种协议适合您项目的要求。

MQTT 与 RabbitMQ

RabbitMQ 是一个开源消息代理,而 MQTT 是一种轻量级的发布-订阅网络协议,专为物联网环境中的机器对机器通信而设计。RabbitMQ 最初仅设计用于处理 AMQP,但已通过插件添加了对 MQTT 以及其他几种协议(如 STOMP 和 HTTP)的协议支持。因此,RabbitMQ 可以用作通用消息代理,它提供了出色的功能,例如故障转移和集群,同时可以根据您的用例更改用于传递消息的协议。

MQTT 与 HTTP

HTTP 是一种请求/响应协议,主要用于互联网应用程序。HTTP 可以用于物联网用例,但并非为此而设计。当在具有不可靠连接的物联网环境中移动数据和处理大量连接设备时,它在消息大小和效率方面存在许多缺点。

MQTT 与 COAP

CoAP 类似于 HTTP,并使用请求/响应模型,并采用二进制格式使其更紧凑。MQTT 使用发布/订阅模型进行通信。CoAP 和 MQTT 之间最大的区别在于 MQTT 专注于成为一种多对多通信协议,通过代理将消息传递给许多客户端设备,而 CoAP 主要用于客户端到服务器的一对一通信。MQTT 可以被认为更适合事件驱动的应用程序,而 CoAP 最适合用于状态传输。

MQTT 与 Zigbee

Zigbee 和 MQTT 之间的主要区别在于 Zigbee 是一种物理数据链路层协议,而 MQTT 是一种应用层协议。Zigbee 专注于数据如何在设备之间实际传输,旨在用作网状网络设备的协议,作为蓝牙或 WiFi 等事物的更简单替代方案。在许多情况下,Zigbee 用作网关协议,然后再最终将数据转换为 MQTT,以便可以将数据传递到云。

MQTT 与 Thread

Thread 是另一种旨在用于低功耗和低延迟应用程序的协议,并且在许多情况下与 Zigbee 非常相似。这样,上面比较 MQTT 和 Zigbee 的大部分信息都适用,MQTT 用于应用层通信,而 Thread 用于较低级别的数据传输。

MQTT over websockets

一些 MQTT 代理提供对 websockets 的支持,这允许您使用 JavaScript 从 Web 浏览器连接到 MQTT 代理。

什么是 OASIS?

OASIS(结构化信息标准促进组织)是负责开发和维护 MQTT 规范以及许多其他项目的联盟。OASIS 于 1993 年成立,是一个专注于称为 SGML 的标记语言的行业协会。随着时间的推移,OASIS 扩展了范围,现在维护着 AMQP、MQTT、SAML 和 Legal XML 等协议。OASIS 成员包括 Oracle、Red Hat、通用汽车、IBM、Microsoft、美国律师协会等。

InfluxDb-cloud-logo

最强大的时间序列
数据库即服务

免费开始使用
Influxdbu

开发者教育

面向时间序列应用开发者的培训。

查看所有教育