编译自: https://opensource.com/article/18/6/mqtt
作者: Sean Dague
译者: Andy Song

从开源数据到开源事宜流,理解一下 MQTT 发布/订阅(pubsub)线路协议。
去年 11 月我们购买了一辆电动汽车,同时也引发了有趣的思考:我们该当什么时候为电动汽车充电?对付电动汽车充电所用的电,我希望能够对应最小的二氧化碳排放,归结为一个特定的问题:对付任意给定时刻,每千瓦时对应的二氧化碳排放量是多少,一天中什么韶光这个值最低?
探求数据我住在纽约州,大约 80% 的电力花费可以自给自足,紧张来自天然气、水坝(大部分来自于 尼亚加拉(Niagara)大瀑布)、核能发电,少部分来自风力、太阳能和其它化石燃料发电。非盈利性组织 纽约独立电网运营商(New York Independent System Operator) (NYISO)卖力全体系统的运作,实现发电机组发电与用电之间的平衡,同时也是纽约路灯系统的监管部门。
只管没有为"大众年夜众供应公开 API,NYISO 还是尽责供应了 不少公开数据 供公众年夜众利用。每隔 5 分钟申报请示全州各个发电机组花费的燃料数据。数据以 CSV 文件的形式发布于公开的档案库中,全天更新。如果你理解不同燃料对发电瓦数的贡献比例,你可以比较准确的估计任意时候的二氧化碳排放情形。
在构建网络处理公开数据的工具时,我们该当时候避免过度利用这些资源。比较将这些数据打包并发送给所有人,我们有更好的方案。我们可以创建一个低开销的 事宜流(event stream),人们可以订阅并第一韶光得到。我们可以利用 MQTT 实现该方案。我的项目( ny-power.org )目标是收录到 Home Assistant 项目中;后者是一个开源的 家庭自动化(home automation)平台,拥有数十万用户。如果所有用户同时访问 CSV 文件做事器,估计 NYISO 不得不增加访问限定。
MQTT 是什么?MQTT 是一个 发布订阅线路协议(publish/subscription wire protocol),为小规模设备设计。发布订阅系统事情事理类似于总线。你将一条发布到一个 主题(topic)上,那么所有订阅了该主题的客户端都可以得到该的一份拷贝。对付发送者而言,无需知道哪些人在订阅;你只需将发布到一系列主题,并订阅一些你感兴趣的主题。就像参加了一场聚会,你选取并加入感兴趣的对话。
MQTT 能够构建极为高效的运用。客户端订阅有限的几个主题,也只收到它们感兴趣的内容。不仅节省了处理韶光,还降落了网络带宽利用。
作为一个开放标准,MQTT 有很多开源的客户端和做事端实现。对付你能想到的每种编程措辞,都有对应的客户端库;乃至有嵌入到 Arduino 的库,可以构建传感器网络。做事端可供选择的大概多,我的选择是 Eclipse 项目供应的 Mosquitto 做事端,这是由于它体积小、用 C 编写,可以承载恒河沙数的订阅者。
为何我喜好 MQTT在过去二十年间,我们为软件运用设计了可靠且准确的模型,用于办理做事碰着的问题。我还有其它邮件吗?当前的景象情形如何?我该当此刻购买这种产品吗?在绝大多数情形下,这种 问答式(ask/receive)的模型事情良好;但对付一个数据爆炸的天下,我们须要其它的模型。MQTT 的发布订阅模型十分强大,可以将大量数据发送到系统中。客户可以订阅数据中的一小部分并在订阅数据发布的第一韶光收到更新。
MQTT 还有一些有趣的特性,个中之一是 遗嘱(last-will-and-testament),可以用于区分两种不同的静默,一种是没有主题干系数据推送,另一种是你的数据吸收器涌现故障。MQTT 还包括 保留(retained message),当客户端初次连接时会供应干系主题的末了一条。这对那些更新缓慢的主题来说很有必要。
我在 Home Assistant 项目开拓过程中,创造这种总线模型对 异构系统(heterogeneous systems)尤为适宜。如果你深入 物联网(Internet of Things)领域,你会创造 MQTT 无处不在。
我们的第一个 MQTT 流NYSO 公布的 CSV 文件中有一个是实时的燃料稠浊利用情形。每 5 分钟,NYSO 发布这 5 分钟内发电利用的燃料类型和相应的发电量(以兆瓦为单位)。
这个 CSV 文件看起来像这样:
表中唯一令人不解便是燃料种别中的稠浊燃料。纽约的大多数天然气工厂也通过燃烧其它类型的化石燃料发电。在冬季寒潮到来之际,家庭供暖的优先级高于发电;但这种情形涌现的次数不多,(在我们打算中)可以将稠浊燃料类型看作天然气类型。
CSV 文件全天更新。我编写了一个大略的数据泵,每隔 1 分钟检讨是否有数据更新,并将新条款发布到 MQTT 做事器的一系列主题上,主题名称基本与 CSV 文件有一定的对应关系。数据内容被转换为 JSON 工具,方便各种编程措辞处理。
ny-power/upstream/fuel-mix/Hydro {\"大众units\公众: \公众MW\"大众, \"大众value\"大众: 3229, \公众ts\公众: \"大众05/09/2018 00:05:00\"大众}
ny-power/upstream/fuel-mix/Dual Fuel {\公众units\"大众: \公众MW\公众, \公众value\公众: 1400, \"大众ts\"大众: \"大众05/09/2018 00:05:00\公众}
ny-power/upstream/fuel-mix/Natural Gas {\"大众units\公众: \"大众MW\公众, \"大众value\"大众: 2144, \公众ts\"大众: \公众05/09/2018 00:05:00\"大众}
ny-power/upstream/fuel-mix/Other Fossil Fuels {\公众units\"大众: \"大众MW\"大众, \"大众value\公众: 4, \"大众ts\"大众: \"大众05/09/2018 00:05:00\公众}
ny-power/upstream/fuel-mix/Wind {\"大众units\"大众: \"大众MW\"大众, \"大众value\"大众: 41, \公众ts\"大众: \"大众05/09/2018 00:05:00\"大众}
ny-power/upstream/fuel-mix/Other Renewables {\"大众units\公众: \"大众MW\公众, \公众value\"大众: 226, \"大众ts\"大众: \"大众05/09/2018 00:05:00\"大众}
ny-power/upstream/fuel-mix/Nuclear {\"大众units\"大众: \"大众MW\"大众, \公众value\"大众: 4114, \"大众ts\"大众: \"大众05/09/2018 00:05:00\"大众}
这种直接的转换是种不错的考试测验,可将公开数据转换为公开事宜。我们后续会连续将数据转换为二氧化碳排放强度,但这些原始数据还可被其它运用利用,用于其它打算用场。
MQTT 主题主题和 主题构造(topic structure)是 MQTT 的一个紧张特色。与其它标准的企业级总线不同,MQTT 的主题无需事先注册。发送者可以凭空创建主题,唯一的限定是主题的长度,不超过 220 字符。个中 / 字符有分外含义,用于创建主题的层次构造。我们即将看到,你可以订阅这些层次中的一些分片。
基于开箱即用的 Mosquitto,任何一个客户端都可以向任何主题发布。在原型设计过程中,这种办法十分便利;但一旦支配莅临盆环境,你须要增加 访问掌握列表(access control list)(ACL)只许可授权的运用发布。例如,任何人都能以只读的办法访问我的运用的主题层级,但只有那些具有特定 凭据(credentials)的客户端可以发布内容。
主题中不包含 自动样式(automatic schema),也没有方法查找客户端可以发布的全部主题。因此,对付那些从 MQTT 总线消费数据的运用,你须要让其直策应用已知的主题和格式样式。
那么该当如何设计主题呢?最佳实践包括利用运用干系的根名称,例如在我的运用中利用 ny-power。接着,为提高订阅效率,构建足够深的层次构造。upstream 层次构造包含了直接从数据源获取的、不经处理的原始数据,而 fuel-mix 层次构造包含特定类型的数据;我们后续还可以增加其它的层次构造。
订阅主题在 MQTT 中,订阅仅仅是大略的字符串匹配。为提高处理效率,只许可如下两种通配符:
# 以递归办法匹配,直到字符串结束+ 匹配下一个 / 之前的内容为便于理解,下面给出几个例子:
ny-power/# - 匹配 ny-power 运用发布的全部主题
ny-power/upstream/# - 匹配全部原始数据的主题
ny-power/upstream/fuel-mix/+ - 匹配全部燃料类型的主题
ny-power/+/+/Hydro - 匹配全部两次层级之后为 Hydro 类型的主题(纵然不位于 upstream 层次构造下)
类似 ny-power/# 的大范围订阅适用于 低数据量(low-volume)的运用,运用从网络获取全部数据并处理。但对 高数据量(high-volume)运用而言则是一个灾害,由于绝大多数并不会被利用,大部分的网络带宽被白白摧残浪费蹂躏了。
在大数据量情形下,为确保性能,运用须要利用恰当的主题筛选(如 ny-power/+/+/Hydro)只管即便准确获取业务所需的数据。
增加我们自己的数据层次接下来,运用中的统统都依赖于已有的 MQTT 流并构建新流。第一个额外的数据层用于打算发电对应的二氧化碳排放。
利用 美国能源情报署(U.S. Energy Information Administration) 给出的 2016 年纽约各种燃料发电及排放情形,我们可以给出各种燃料的 均匀排放率 ,单位为克/兆瓦时。
上述结果被封装到一个专用的微做事中。该微做事订阅 ny-power/upstream/fuel-mix/+,即数据泵中燃料组成情形的原始数据,接着完成打算并将结果(单位为克/千瓦时)发布到新的主题层次构造上:
ny-power/computed/co2 {\"大众units\"大众: \公众g / kWh\"大众, \公众value\"大众: 152.9486, \公众ts\"大众: \公众05/09/2018 00:05:00\公众}
接着,另一个做事会订阅该主题层次构造并将数据打包到 InfluxDB 进程中;同时,发布 24 小时内的韶光序列数据到 ny-power/archive/co2/24h 主题,这样可以大大简化当前变革数据的绘制。
这种层次构造的主题模型效果不错,可以将上述程序之间的逻辑解耦合。在繁芜系统中,各个组件可能利用不同的编程措辞,但这并不主要,由于交流格式都是 MQTT ,即主题和 JSON 格式的内容。
从终端消费数据为了更好的理解 MQTT 完成了什么事情,将其绑定到一个总线并查看流是个不错的方法。mosquitto-clients 包中的 mosquitto_sub 可以让我们轻松实现该目标。
安装程序后,你须要供应做事器名称以及你要订阅的主题。如果有须要,利用参数 -v 可以让你看到有新发布的那些主题;否则,你只能看到主题内的数据。
mosquitto_sub -h mqtt.ny-power.org -t ny-power/# -v
只要我编写或调试 MQTT 运用,我总会在一个终端中运行 mosquitto_sub。
从网页直接访问 MQTT到目前为止,我们已经有供应公开事宜流的运用,可以用微做事或命令行工具访问该运用。但考虑到互联网仍霸占主导地位,因此让用户可以从浏览器直接获取事宜流是很主要。
MQTT 的设计者已经考虑到了这一点。协议标准支持三种不同的传输协议: TCP 、 UDP 和 WebSockets 。主流浏览器都支持 WebSockets,可以坚持持久连接,用于实时运用。
Eclipse 项目供应了 MQTT 的一个 JavaScript 实现,叫做 Paho ,可包含在你的运用中。事情模式为与做事器建立连接、建立一些订阅,然后根据吸收到的进行相应。
// ny-power web console application
var client = new Paho.MQTT.Client(mqttHost, Number(\"大众80\"大众), \"大众client-\"大众 + Math.random());
// set callback handlers
client.onMessageArrived = onMessageArrived;
// connect the client
client.reconnect = true;
client.connect({onSuccess: onConnect});
// called when the client connects
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
console.log(\"大众onConnect\"大众);
client.subscribe(\"大众ny-power/computed/co2\"大众);
client.subscribe(\"大众ny-power/archive/co2/24h\"大众);
client.subscribe(\"大众ny-power/upstream/fuel-mix/#\公众);
}
// called when a message arrives
function onMessageArrived(message) {
console.log(\"大众onMessageArrived:\"大众+message.destinationName + message.payloadString);
if (message.destinationName == \"大众ny-power/computed/co2\"大众) {
var data = JSON.parse(message.payloadString);
$(\"大众#co2-per-kwh\公众).html(Math.round(data.value));
$(\"大众#co2-units\"大众).html(data.units);
$(\"大众#co2-updated\"大众).html(data.ts);
}
if (message.destinationName.startsWith(\公众ny-power/upstream/fuel-mix\公众)) {
fuel_mix_graph(message);
}
if (message.destinationName == \公众ny-power/archive/co2/24h\"大众) {
var data = JSON.parse(message.payloadString);
var plot = [
{
x: data.ts,
y: data.values,
type: 'scatter'
}
];
var layout = {
yaxis: {
title: \公众g CO2 / kWh\"大众,
}
};
Plotly.newPlot('co2_graph', plot, layout);
}
上述运用订阅了不少主题,由于我们将要呈现多少种不同类型的数据;个中 ny-power/computed/co2 主题为我们供应当前二氧化碳排放的参考值。一旦收到该主题的新,网站上的相应内容会被相应更换。
ny-power.org 网站供应的 NYISO 二氧化碳排放图。
ny-power/archive/co2/24h 主题供应了韶光序列数据,用于为 Plotly 线表供应数据。ny-power/upstream/fuel-mix 主题供应当前燃料组成情形,为俊秀的柱状图供应数据。
ny-power.org 网站供应的燃料组成情形。
这是一个动态网站,数据不从做事器拉取,而是结合 MQTT 总线,监听对外开放的 WebSocket。就像数据泵和打包器程序那样,网站页面也是一个发布订阅客户端,只不过是在你的浏览器中实行,而不是在公有云的微做事上。
你可以在 http://ny-power.org 站点点看到动态变更,包括图像和可以看达到到的实时 MQTT 终端。
连续深入ny-power.org 运用的完全内容开源在 GitHub 中。你也可以查阅 架构简介 ,学习如何利用 Helm 支配一系列 Kubernetes 微做事构建运用。另一个有趣的 MQTT 示例利用 MQTT 和 OpenWhisk 进行实时文本翻译, 代码模式(code pattern)参考 链接 。
MQTT 被广泛运用于物联网领域,更多关于 MQTT 用场的例子可以在 Home Assistant 项目中找到。
如果你希望深入理解协议内容,可以从 mqtt.org 得到该公开标准的全部细节。
想理解更多,可以参加 Sean Dague 在 OSCON 上的演讲,主题为 将 MQTT 加入到你的工具箱 ,会议将于 7 月 16-19 日在奥尔良州波特兰举办。
via: https://opensource.com/article/18/6/mqtt
作者: Sean Dague 选题: lujun9972 译者: pinewall 校正: wxy
本文由 LCTT 原创编译, Linux中国 名誉推出
点击“理解更多”可访问文内链接