Elasticsearch 可以存储 PB 级的数据并实时分析数据,而 MQTT 被广泛使用于物联网中。那么我们该如果把 MQTT 的数据传入到 Elasticsearch 中呢?
我们可以通过如下的架构来把 MQTT 数据传入到 Elasticsearch:
在这里,我们可以通过一个叫做 MQTT 的 router 来把数据传入到 Elasticsearch。这些物联网的数据可以包括温度,速度,位置,速度,湿度,重力加速度,光感等。
下面,我们来介绍一下如何实现把 MQTT 的数据接入到 Elasticsearch 中来。为了说明问题方便,我们的测试环境是这样的:
如上图所示,我们在 MacOS 上安装好自己的 Elastic Stack。在 Ubuntu 18.04 的机器上安装好自己的 MQTT broker 及运行 MQTT 的 publisher。
准备工作
安装 Elasticsearch
如果大家还没安装好自己的 Elastic Stack 的话,那么请按照我之前的教程 “如何在Linux,MacOS及Windows上进行安装Elasticsearch” 安装好自己的 Elasticsearch。由于我们的Elastic Stack需要被另外一个 Ubuntu VM 来访问,我们需要对我们的 Elasticsearch 进行配置。首先使用一个编辑器打开在 config 目录下的 elasticsearch.yml 配置文件。我们需要修改 network.host 的 IP 地址。在你的 Mac 及 Linux 机器上,我们可以使用:
$ ifconfig
来查看到我们的机器的 IP 地址。针对我的情况,我的机器的 IP 地址是:192.168.0.100。
我们也必须在 elasticsearch.yml 的最后加上 discovery.type: single-node,表明我们是单个 node。
等修改完我们的 IP 地址后,我们保存 elasticsearch.yml 文件。然后重新运行我们的 elasticsearch。我们可以在一个浏览器中输入刚才输入的 IP 地址并加上端口号 9200。这样可以查看一下我们的 elasticsearch 是否已经正常运行了。
安装 Kibana
我们可以按照 “如何在Linux,MacOS及Windows上安装Elastic栈中的Kibana” 中介绍的那样来安装我们的 Kibana。由于我们的 Elasticsearch 的 IP 地址已经改变,所以我们必须修改我们的 Kibana 的配置文件。我们使用自己喜欢的编辑器打开在 config 目录下的 kibana.yml 文件,并找到 server.host。把它的值修改为自己的电脑的IP地址。针对我的情况是:
同时找到 elasticsearch.hosts,并把自己的 IP 地址输入进去:
保存我们的 kibana.yml 文件,并运行我们的 Kibana。同时在浏览器的地址中输入自己的 IP 地址及 5601 端口:
如果配置成功的话,我们就可以看到上面的画面。
安装 Ubuntu 虚拟机
这个不在我的这个教程之内。在网上我们可以找到许多的教程教我们如何安装 Ubuntu 虚拟机。
安装 MQTT mosquito
我们在 Ubuntu 机器里,执行如下的指令:
sudo apt-get update
sudo apt-get install -y python-paho-mqtt
一旦上面的命令执行成功后,我们可以通过如下的命令来检查 mosquito 服务是否已经成功运行:
sudo systemctl status mosquitto
更多关于 mosquito 的安装请参阅链接。
我们也可以同时执行如下的指令来安装 MQTT 的客户端:
sudo apt-get install mosquitto-clients
安装 Python 2 及 Elasticsearch Python
我们可以按照如下的指令来安装 python 2:
sudo apt install python-minimal
然后我们打入如下的指令来安装Elasticsearch Python:
sudo apt install python-elasticsearch
到目前位置我们的安装基本上已经完成了。
MQTT router
在我们的实现中,我们使用 Python 语言来实现对 MQTT 信息的转发。其基本原理是订阅我们所感兴趣的 topic,然后把我们截获的数据再转发到 Elasticsearch 中。我们可以通过如下的指令来下载我的测试程序:
git clone https://github.com/liu-xiao-guo/mqtt-elasticSearch
具体实现如下:
mqttToElasticSearch.py
mqttServer="localhost"
mqttPort="1883"
channelSubs="test"
#use below as alternative to subscribe to all channels
#channelSubs="#"
import paho.mqtt.client as mqtt
from datetime import datetime
from elasticsearch import Elasticsearch
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe(channelSubs)
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
# this is the syntax to follow for the elasticSearch update taken from documentation
# es.index(index="mqtt-index", doc_type="_doc", id=42, body={"any": +str(msg.payload, "timestamp": datetime.now()})
# {u'_id': u'42', u'_index': u'my-index', u'_type': u'test-type', u'_version': 1, u'ok': True}
#our implementation uses this to separate numeric(float) from string data
try:
float(msg.payload)
es.index(index="mqtt-index", doc_type="_doc", body={"topic" : msg.topic, "dataFloat" : float(msg.payload), "timestamp": datetime.utcnow()})
except:
pass
#es.index(index="my-index", doc_type="string", body={"topic" : msg.topic, "dataString" : msg.payload, "timestamp": datetime.utcnow()})
# by default we connect to elasticSearch on localhost:9200
es = Elasticsearch(
['192.168.0.100'],
http_auth=('user', 'secret'),
scheme="https",
port=9200,
)
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(mqttServer,mqttPort, 60)
# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
client.loop_forever()
在这里,我使用了一个叫做 test 的 topic 来做测试。在实际的使用中,需要根据自己的需求来调整。同时在 Elasticsearch 的初始化过程中,我们需要填入自己的 IP 地址:
es = Elasticsearch(
['192.168.0.100'],
http_auth=('user', 'secret'),
scheme="https",
port=9200,
)
我们向 Elasticsearch 中写入一个叫做 mqtt-index 的索引。
我们可以通过如下的方式来运行我们的 router:
python2 mqttToElasticSearch.py
我们可以在另外一个 terminal 中打入如下的指令:
mosquitto_pub -m "1" -t "test"
请注意这里的 mosquitto_pub 是来自上面的 mosquitto-clients 安装。那么这个时候再我们的 mqttToElasticSearch.py 运行的客户端中,我们可以看到:
显然我们的router已经收到者信息。我们可以在Kinaba中查看mqtt-index:
GET mqtt-index/_search
显示结果:
"hits" : [
{
"_index" : "mqtt-index",
"_type" : "_doc",
"_id" : "Ce0pkm8B9t-DLEX5oV8G",
"_score" : 1.0,
"_source" : {
"topic" : "test",
"timestamp" : "2020-01-11T01:13:07.278997",
"dataFloat" : 1.0
}
},
{
"_index" : "mqtt-index",
"_type" : "_doc",
"_id" : "CO0pkm8B9t-DLEX5oF8_",
"_score" : 1.0,
"_source" : {
"topic" : "test",
"timestamp" : "2020-01-11T01:13:07.279708",
"dataFloat" : 1.0
}
}
]
}
在上面的数据显示我们的 Elasticsearch 已经成功地收到数据了。
我们也可以使用在git项目中的 publisher.py 来发送信息:
publisher.py
#!/usr/bin/env python2
import paho.mqtt.client as mqtt
import sys
print ("argv[0]: %s" % (sys.argv[1]))
client = mqtt.Client()
client.connect("localhost",1883,60)
client.publish("test", sys.argv[1]);
我们可以按照如下的命令来发送信息:
python2 publisher.py 5
至此,我们已经成功地把我们的 MQTT 数据发送到了 Elasticsearch。
如果有兴趣的开发者,也可以参照项目https://github.com/nathan-K-/mqttbeat。由于一些原因,该项目不能很好地和最新版本的 Elasticsearch 工作。需要作者更进一步完善。