前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在DC / OS上构建高度可扩展的物联网平台

如何在DC / OS上构建高度可扩展的物联网平台

作者头像
February
发布2018-12-11 15:31:59
3.6K0
发布2018-12-11 15:31:59
举报
文章被收录于专栏:技术翻译技术翻译技术翻译

我最近一直在使用新的Percona-Server-MongoDB DC / OS服务,作为这项工作的一部分,我决定尝试使用Percona-Server-MongoDB作为持久存储后端构建IoT架构。MongoDB是物联网架构中持久存储的一种流行选择,原因有很多,包括高可伸缩性,对复杂查询的支持,以及它不需要严格的模式,因此您可以使用不同的原生JSON将文档推送到它每个字段的类型。如果您想运行此博客中使用的代码,您可以在GitHub上找到所有内容。

让我们首先看一下我们要部署的平台的整体架构:

在顶部,我们有许多使用MQTT协议的数据生成器设备。MQTT是为传感器设计的标准化协议,基于发布/订阅模型。它最初是由IBM前英国同事Andy Stanford-Clark在IBM开发的,旨在运行在处理开销非常低的设备上。由于我们的演示环境中没有真正的设备,因此我使用Eclipse Paho python库来模拟具有单个传感器的设备,以可配置的采样率提供随机输出。这可以是工业传感器,例如给出温度输出。

MQTT生产者需要连接到代理来发布他们的数据,在我们的例子中,我们将使用开源的Eclipse Mosquitto代理。

为了从我们的采集层代理到MongoDB的聚合层,我们需要某种网关,它将订阅我们的代理上的相关主题,获取新消息,重新格式化它们,然后将它们写入MongoDB副本设置在后端。我再次使用paho-mqtt和pymongo库将实现为基于Python的服务。

让我们从模拟设备开始更详细地看一下这些元素。这个代码非常简单:

#!/usr/bin/env python
"""
MQTT generator
"""
import random
import time
import uuid
import json
from argparse import ArgumentParser
import paho.mqtt.client as mqtt
parser = ArgumentParser()
parser.add_argument("-b", "--broker", dest="broker_address",
required=True, help="MQTT broker address")
parser.add_argument("-p", "--port", dest="broker_port", default=1883, help="MQTT broker port")
parser.add_argument("-r", "--rate", dest="sample_rate", default=5, help="Sample rate")
parser.add_argument("-q", "--qos", dest="qos", default=0, help="MQTT QOS")
args = parser.parse_args()
uuid = str(uuid.uuid4())
topic = "device/%s" % uuid
mqttc = mqtt.Client(uuid, False)
mqttc.connect(args.broker_address, args.broker_port)
while True:
rand = random.randint(20,30)
msg = {
'uuid': uuid,
'value': rand
}
mqttc.publish(topic, payload=json.dumps(msg), qos=args.qos)
time.sleep(float(args.sample_rate))
mqttc.loop_forever()

我们可以看到,我们的设备需要一些不同的参数。首先,我们需要查看要连接的MQTT代理的地址和端口,我们想要生成值的速率以及当前未使用的QOS设置。QOS(服务质量)是MQTT标准的一部分,您可以在Mosquitto文档中了解更多相关信息。

在启动时,设备生成唯一的UUID,在设备/ $ uuid主题上连接到MQTT代理,然后在每个采样周期生成一个范围内的随机数,然后发布包含其UUID和值的小JSON有效负载。 。

为了在DC / OS上运行它,我们可以使用pyinstaller捆绑我们的依赖项,如我之前关于Python微服务的博客文章中所述,但在这种情况下,我们将构建一个Docker镜像并将其发布到存储库。我不打算在你的环境中安装Docker; 互联网上有很多很棒的操作方法可以帮助解决这个问题,因此我们假设您已经在本地拥有了一个可用的Docker环境。

首先,我们想要生成一个包含我们应用程序要求的文本文件。我在virtualenv中开发了这个,从pip安装我的依赖项,所以我可以通过运行来实现:

$ pip freeze > requirements.txt
$ cat requirements.txt
paho-mqtt==1.3.1

我们的下一步是创建一个Dockerfile,我们将使用它来构建Docker镜像。在我们的例子中这非常简单:

$ cat Dockerfile
FROM python:2
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY device.py .
CMD [ "/bin/bash" ]

在我们的例子中,我们将使用标准的Python 2 Docker镜像作为基础,我们将在我们的requirements.txt中复制,使用它来使用pip安装我们的依赖项,然后复制我们的实际设备代码。由于我们将使用Universal Container Runtime运行它,我们实际上并不需要在这里定义CMD,但出于测试目的,我只是将其设置为运行shell。

现在我们已经有了Dockerfile,我们可以继续构建我们的Docker镜像:

$ docker build -t device .
Sending build context to Docker daemon 12.78MB
Step 1/6 : FROM python:2
2: Pulling from library/python
0bd44ff9c2cf: Pull complete
047670ddbd2a: Pull complete
ea7d5dc89438: Pull complete
ae7ad5906a75: Pull complete
0f2ddfdfc7d1: Pull complete
85124268af27: Pull complete
1be236abd831: Pull complete
fe14cb9cb76d: Pull complete
cb05686b397d: Pull complete
Digest: sha256:c45600ff303d92e999ec8bd036678676e32232054bc930398da092f876c5e356
Status: Downloaded newer image for python:2
---> 0fcc7acd124b
Step 2/6 : WORKDIR /usr/src/app
Removing intermediate container ea5359354513
---> a382209b69ea
Step 3/6 : COPY requirements.txt ./
---> b994369a0a58
Step 4/6 : RUN pip install --no-cache-dir -r requirements.txt
---> Running in 1e60a96f7e7a
Collecting paho-mqtt==1.3.1 (from -r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/2a/5f/cf14b8f9f8ed1891cda893a2a7d1d6fa23de2a9fb4832f05cef02b79d01f/paho-mqtt-1.3.1.tar.gz (80kB)
Installing collected packages: paho-mqtt
Running setup.py install for paho-mqtt: started
Running setup.py install for paho-mqtt: finished with status 'done'
Successfully installed paho-mqtt-1.3.1
Removing intermediate container 1e60a96f7e7a
---> 3340f783442b
Step 5/6 : COPY device.py .
---> 72a88b68e43c
Step 6/6 : CMD [ "/bin/bash" ]
---> Running in a128ffb330fc
Removing intermediate container a128ffb330fc
---> dad1849c3966
Successfully built dad1849c3966
Successfully tagged device:latest
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
device latest dad1849c3966 About an hour ago 903MB
python 2 0fcc7acd124b 9 days ago 902MB

现在我们在本地拥有Docker镜像,我们想要发布它,以便我们以后可以使用DC / OS中的Marathon来部署它。首先,我们需要确保我们登录Dockerhub:

$ docker login --username=mattjarvis
Password:
Login Succeeded

现在,我们需要标记我们的本地图像:

$ docker tag dad1849c3966 mattjarvis/device:latest

图像被标记后,我们可以推送到我们的存储库:

$ docker push mattjarvis/device
The push refers to repository [docker.io/mattjarvis/device]
d52256b6a396: Pushed
6b19db956ca6: Pushed
cd0c68b16296: Pushed
812812e9c2f5: Pushed
05331f1f8e6f: Layer already exists
d8077e47eb94: Layer already exists
5c0800b60a4e: Layer already exists
ebc569cb707f: Layer already exists
9df2ff4714f2: Layer already exists
c30dae2762bd: Layer already exists
43701cc70351: Layer already exists
e14378b596fb: Layer already exists
a2e66f6c6f5f: Layer already exists
latest: digest: sha256:8a1407f64dd0eff63484f8560b605021fa952af00552fec6c8efb913d5bba076 size: 3053

在我们开始实际部署之前,让我们看看我们的第二段代码,它是我们的MQTT代理和MongoDB集群之间的连接器。同样,这是用Python编写的:

$ cat mongogw.py
#!/usr/bin/env python
"""
MQTT to MongoDB Gateway
"""
import json
from argparse import ArgumentParser
import paho.mqtt.client as mqtt
import pymongo
import datetime
import osxxxxxxxxxx $ cat mongogw.py$ cat mongogw.py#!/usr/bin/env python"""MQTT to MongoDB Gateway"""import jsonfrom argparse import ArgumentParserimport paho.mqtt.client as mqttimport pymongoimport datetimeimport os
parser = ArgumentParser()
parser.add_argument("-b", "--broker", dest="broker_address",
required=True, help="MQTT broker address")
parser.add_argument("-p", "--port", dest="broker_port", default=1883, help="MQTT broker port")
parser.add_argument("-m", "--mongouri", dest="mongo_uri", required=True, help="MongoDB URI")
parser.add_argument("-u", "--mongouser", dest="mongo_user", required=True, help="MongoDB user")
parser.add_argument("-w", "--mongopwd", dest="mongo_password", required=True, help="MongoDB password")
args = parser.parse_args()
def on_message(client, userdata, message):
json_data = json.loads(message.payload)
post_data = {
'date': datetime.datetime.utcnow(),
'deviceUID': json_data['uuid'],
'value': json_data['value'],
'gatewayID': os.environ['MESOS_TASK_ID']
}
result = devices.insert_one(post_data)
# MongoDB connection
mongo_client = pymongo.MongoClient(args.mongo_uri,
username=args.mongo_user,
password=args.mongo_password,
authSource='mongogw',
authMechanism='SCRAM-SHA-1')
db = mongo_client.mongogw
devices = db.devices
# MQTT connection
mqttc = mqtt.Client("mongogw", False)
mqttc.on_message=on_message
mqttc.connect(args.broker_address, args.broker_port)
mqttc.subscribe("device/#", qos=0)
mqttc.loop_forever()

在这种情况下,我们连接到MQTT代理和MongoDB,然后我们订阅所有前缀为MQTT的主题 device/然后在每次我们读取消息时重新格式化消息并在将其写入MongoDB之前添加我们自己的一些额外元数据时使用回调函数。我们在此阶段添加时间戳,这反映了在实际示例中,我们的传感器设备可能没有足够的处理能力来提供时钟功能的可能性。我们还添加了网关进程的Mesos任务ID,这将允许我们在扩展采集层时跟踪消息通过的网关。

我们将以与设备示例完全相同的方式构建它,使用Dockerfile并将Docker镜像推送到存储库。这个Dockerfile非常类似于这个设备:

$ cat Dockerfile
FROM python:2
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install –no-cache-dir -r requirements.txt
COPY mongogw.py .
CMD [ “/bin/bash” ]

现在我们已经有了自定义代码,让我们继续开始部署。我们要部署的第一件事是我们的MongoDB副本集。我写了一篇关于Percona-Server-MongoDB服务的更长篇文章,你可以在其中找到有关此服务的高级功能集的更多信息,但是为了本演示的目的,我们将只使用默认值,这将给我们三节点副本集。首先,我们需要创建一个配置文件来设置默认用户,密码和密钥。它应该看起来像这样:

$ cat demo.json
{
"mongodb-credentials": {
"backupUser": "backup",
"backupPassword": "backupuserpassword",
"userAdminUser": "useradmin",
"userAdminPassword": "useradminpassword",
"clusterAdminUser": "clusteradmin",
"clusterAdminPassword": "clusteradminpassword",
"clusterMonitorUser": "clustermonitor",
"clusterMonitorPassword": "monitoruserpassword",
"key": "8cNNTVP6GqEOKzhUVDVryxIt04K6kDbXygamH4upPGAO59gzXVQAgX9NwxwqDvpt 094zMkkRWDLzuCgbg3Aj8EFVEM0/W1Nz+XUSTHEn4HiNzCVG4TTHFP6P1PEPswG6 tQMP6bnRXL7uGWmdGhbAxOV/+p6AfNs67MTvfCeH0EaPCgPPXhJft9D0nZ0SPOm9 VvfxG3djnHClIlclkchoIwc1Kw21loyXwuOjX4RkywVDdmFXjKC+l9yxfyt/9Gyh YE0OlS7ozWLiH8zy0MyzBdK+rc0fsxb2/Kb/8/2diC3O3gdVxjneQxaf66+FHVNW mV9/IHDptBHosdWkv0GboW8ZnTXnk0lyY0Jw85JFuTeFBzqPlB37jR0NU/HFm5QT Ld62woaGIWCTuXGb81QHaglPZUBIhEq/b3tahJBmLc+LKd0FUShoupTtPc2FjxbH xD8dZ+L9Uv7NPtSe+o3sTD60Pnsw1wbOrNDrrC+wpwoMy2GbQjXk/d+SRK/CXfuk Z676GKQDivpinhdF58l4OEi+WEN633yuNtNAQDgz+aOVZKN4oLoyR22B1nrea1qW wzZjRw7kpVxcQKiyn+gDmAZZPbctiVqTNHPE5n9LrOcctuLZKpoQk97lvZTSCKfy d32mfx9szZZ/QCfF9Dt7+G5nJUAULigKnQYRi/i86ZTPHSzfun+ZIzYLCzJuZfyS 7E8DMsmv9wCPrPAF/8cOFMWW0o0Na7GZKCJ8U+AMm92R725h4g5ao6+kQPG7vOkY LR8MJzDOqcmAC0M9AwE5UXQl56V6qBNyREx/WGGYS1B5DOfZvVTJNDkoHVIL1upZ geSlACiXQ+M0Rkgo0h8BJUhGY9LTuc6S8qiMBEnhBClg4kA/u4FJ06nlmF3ZpIXT KsVSr9ee3mu0vSr6P52slvAAX+RL3y+JgSlz2kC8oVgCZZdKn7yq9e6yB3zHNMjX 8VIi/UgFmfqCiaAlUT0pt2ZzGuw1L9QUOuNAZfufSkK1ED4V"
}
}

用户的密码必须至少包含10个字符,密钥长度必须至少为1024个字符。您可以在MacOS上生成适当的密钥,使用:

$ openssl rand -base64  756

现在我们有了options.json,我们可以使用它来安装包:

$ dcos package install percona-server-mongodb --options=demo.json
By Deploying, you agree to the Terms and Conditions https://mesosphere.com/catalog-terms-conditions/#community-services
Default configuration requires 3 agent nodes each with: 1.0 CPU | 1024 MB MEM | 1 1000 MB Disk
Continue installing? [yes/no] yes
Installing Marathon app for package [percona-server-mongodb] version [0.4.0-3.6.6]
Installing CLI subcommand for package [percona-server-mongodb] version [0.4.0-3.6.6]
New command available: dcos percona-server-mongodb
The DC/OS Percona Server for MongoDB service is being installed.
Documentation: https://docs.mesosphere.com/service-docs/percona-server-mongodb/
Issues: https://jira.percona.com/secure/CreateIssue!default.jspa?pid=12402.

我们还想为我们将要使用的数据库配置用户。我们可以使用Percona-Server-MongoDB CLI扩展直接从DC / OS CLI执行此操作。首先,我们需要创建一个JSON文件来定义我们想要创建的用户:

$ cat mongouser.json
{
"user": "mongogw",
"pwd": "123456",
"roles": [
{ "db": "mongogw", "role": "readWrite" }
]
}$ cat mongouser.json

现在,我们将其传递给CLI,以及数据库的名称,以及具有用户管理权限的管理员用户的凭据:

$ dcos percona-server-mongodb user add mongogw mongouser.json
{
"message": "Received cmd: start update-user with parameters: {MONGODB_CHANGE_USER_DB=mongogw, MONGODB_CHANGE_USER_DATA=eyJ1c2VycyI6W3sidXNlciI6Im1vbmdvZ3ciLCJwd2QiOiIxMjM0NTYiLCJyb2xlcyI6W3sicm9sZSI6InJlYWRXcml0ZSIsImRiIjoibW9uZ29ndyJ9XX1dfQ==}"
}

接下来,我们将部署MQTT层。由于我们理论上可能有数千个设备,因此我们的采集层是可扩展的。我们将在MQTT端通过使用DC / OS中的命名VIP对多个Mosquitto端点实例进行负载平衡来实现此目的。虽然在面向Internet的现实世界中,我们可能会使用在集群外部暴露的Marathon-LB实例。

虽然这将适用于面向设备,但如果我们要使用来自网关层的VIP并且我们希望网关层也可以扩展,那么我们可能最终会丢失数据,因为我们的网关可以从任何一个读取Mosquitto实例和MQTT层未集群。为了解决这个问题,我们将每个Mosquitto实例与它自己的专用网关微服务一起部署,并让网关微服务通过localhost连接连接到Mosquitto,确保每个网关只从单个Mosquitto实例获取数据。因此,对于通过负载均衡器地址连接的设备,它可以连接到我们部署的任何Mosquitto实例,我们的存储层将获取数据。

这是我们将用于部署pod的JSON:

{
"id": "/mqtt",
"containers": [
{
"name": "mosquitto",
"resources": {
"cpus": 0.1,
"mem": 64
},
"image": {
"id": "eclipse-mosquitto",
"kind": "DOCKER"
},
"endpoints": [
{
"name": "mqtt",
"containerPort": 1883,
"hostPort": 1883,
"protocol": [
"tcp"
],
"labels": {
"VIP_0": "/mqtt:1883"
}
}
]
},
{
"name": "mongogw",
"resources": {
"cpus": 0.1,
"mem": 64
},
"image": {
"id": "mattjarvis/mongogw",
"kind": "DOCKER"
},
"exec": {
"command": {
"shell": "./mongogw.py -b localhost -m mongo-rs-0-mongod.percona-server-mongodb.autoip.dcos.thisdcos.directory,mongo-rs-1-mongod.percona-server-mongodb.autoip.dcos.thisdcos.directory,mongo-rs-2-mongod.percona-server-mongodb.autoip.dcos.thisdcos.directory:27017 -u mongogw -n 123456"
}
}
}
],
"scaling": {
"instances": 1,
"kind": "fixed"
},
"networks": [
{
"name": "dcos",
"mode": "container"
}
],
"volumes": [],
"fetch": [],
"scheduling": {
"placement": {
"constraints": []
}
}
}

Mosquitto提供了预先构建的Docker镜像,因此我们将其用于第一个容器。我们还需要为MQTT连接公开端口1883,因此我们将其映射到主机上的端口并通过负载平衡VIP公开它。

第二个容器是我们的mongogw Python微服务,它将启动mongogw进程,通过localhost连接到Mosquitto,使用每个MongoDB实例的DC / OS分配的DNS名称连接到MongoDB副本集。

要运行它,我们只需使用DC / OS CLI将JSON传递给Marathon:

$ dcos marathon pod add mqttpod.json
Created deployment 19887892-f3e9-44b4-9dd3-22a5790196f3

现在我们的采集层已经启动并运行,我们可以启动我们的设备。在这里我们还需要一些JSON中的Marathon配置:

{
"id": "device",
"instances": 1,
"cpus": 0.1,
"mem": 16,
"cmd": "./device.py -b mqtt.marathon.l4lb.thisdcos.directory -r 2",
"container": {
"type": "MESOS",
"docker": {
"image": "mattjarvis/device",
"forcePullImage": true,
"privileged": false
}
},
"requirePorts": false
}

我们将使用Universal Container Runtime,拉出相关的Docker镜像,并运行带有一些参数的python脚本,配置设备以连接到我们为Mosquitto pod分配的负载平衡VIP,并以2秒的间隔发布。我们可以看到,对此的CPU和RAM要求非常小,因此我们应该能够扩展它并运行许多实例。

那么,让我们继续部署我们的第一个设备:

$ dcos marathon app add device.json
Created deployment 231be2c7-47c6-4f28-a7e0-40f4aae2f743

一旦我们的第一台设备启动并运行,我们就可以检查MongoDB以确保所有层都正常运行。首先,我们需要一个MongoDB副本集的任务ID:

$ dcos task
NAME HOST USER STATE ID MESOS ID REGION ZONE
admin-0-watchdog 10.0.2.229 root R admin-0-watchdog__a3ff9cc4-daeb-4f76-b730-aea8e2667417 3ba115f5-b4fe-43e9-a05a-0d9b0240fb51-S4 --- ---
device 10.0.3.192 root S device.769ef300-b75d-11e8-9d5d-fe0bc23c90b8 3ba115f5-b4fe-43e9-a05a-0d9b0240fb51-S3 --- ---
mongo-rs-0-mongod 10.0.0.44 root R mongo-rs-0-mongod__f0a27fca-138a-4f39-a0b2-4a1a0960c079 3ba115f5-b4fe-43e9-a05a-0d9b0240fb51-S6 --- ---
mongo-rs-1-mongod 10.0.3.152 root R mongo-rs-1-mongod__a039fb0f-6ca7-4706-974a-855542fa5e36 3ba115f5-b4fe-43e9-a05a-0d9b0240fb51-S2 --- ---
mongo-rs-2-mongod 10.0.0.26 root R mongo-rs-2-mongod__5c68c451-c11d-49bd-bf49-e99b8bcceb5c 3ba115f5-b4fe-43e9-a05a-0d9b0240fb51-S1 --- ---
mongogw 10.0.0.44 root R mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw 3ba115f5-b4fe-43e9-a05a-0d9b0240fb51-S6 --- ---
mosquitto 10.0.0.44 root R mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mosquitto 3ba115f5-b4fe-43e9-a05a-0d9b0240fb51-S6 --- ---
percona-server-mongodb 10.0.0.26 root R percona-server-mongodb.cfbfcaae-b75b-11e8-9d5d-fe0bc23c90b8 3ba115f5-b4fe-43e9-a05a-0d9b0240fb51-S1 --- ---

一旦我们有了任务ID,我们就可以使用DC / OS CLI在该容器中获取shell:

$ dcos task exec --tty --interactive mongo-rs-0-mongod__f0a27fca-138a-4f39-a0b2-4a1a0960c079 /bin/bash
root@ip-10-0-0-44:/mnt/mesos/sandbox#

然后,我们将使用mongo shell连接到MongoDB:

root@ip-10-0-0-44:/mnt/mesos/sandbox# mongo mongodb://mongogw:123456@mongo-rs-0-mongod.percona-server-mongodb.autoip.dcos.thisdcos.directory,mongo-rs-1-mongod.percona-server-mongodb.autoip.dcos.thisdcos.directory,mongo-rs-2-mongod.percona-server-mongodb.autoip.dcos.thisdcos.directory:27017/mongogw?replicaSet=rs

请注意,我们使用的是我们之前创建的用户,以及每个MongoDB副本集的自动分配的DC / OS DNS条目。

现在,我们应该以MongoDB shell提示符结束,所以让我们切换到我们的数据库:

rs:PRIMARY> use mongogw;
switched to db mongogw

从这里,我们可以计算我们现在在设备集合中有多少条目:

rs:PRIMARY> db.devices.count();
117

而且,我们还可以查看插入的数据:

rs:PRIMARY> db.devices.findOne();
{
"_id" : ObjectId("5b9a6db71284f4000452fd31"),
"date" : ISODate("2018-09-13T14:01:27.529Z"),
"deviceUID" : "f5265ed9-a162-4c72-926d-f537b0ef356c",
"value" : 22,
"gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw"
}

从此输出中,我们可以看到来自网关进程的重新格式化数据,该数据还添加了时间戳,以及DC / OS中网关进程的任务ID。

因此,我们现在可以看到为我们的单个设备获取的数据。让我们扩大设备。在我们的device.json中,让我们将数字增加到3:

$ cat device.json
{
"id": "device",
"instances": 3,
"cpus": 0.1,
"mem": 16,
"cmd": "./device.py -b mqtt.marathon.l4lb.thisdcos.directory -r 2",
"container": {
"type": "MESOS",
"docker": {
"image": "mattjarvis/device",
"forcePullImage": true,
"privileged": false
}
},
"requirePorts": false
}

现在,我们将使用修改后的JSON来更新我们的应用:

$ dcos marathon app update device < device.json Created deployment 83c91f20-9944-4933-943b-90cee2711640$ dcos马拉松应用更新设备<device.json创建部署83c91f20-9944-4933-943b-90cee2711640

当我们查看DC / OS UI时,我们可以看到我们现在有三个设备实例。我们现在还可以在MongoDB层接收的数据中看到不同的UUID:

rs:PRIMARY> db.devices.find().limit(5).sort({$natural:-1})
{ "_id" : ObjectId("5b9a6ef01284f4000452fdef"), "date" : ISODate("2018-09-13T14:06:40.698Z"), "deviceUID" : "919473a4-b332-4929-9b5e-c0a80f498222", "value" : 24, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }
{ "_id" : ObjectId("5b9a6ef01284f4000452fdee"), "date" : ISODate("2018-09-13T14:06:40.165Z"), "deviceUID" : "9474a1ee-c1c7-4f1d-a012-c6e4c883c7d3", "value" : 27, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }
{ "_id" : ObjectId("5b9a6eef1284f4000452fded"), "date" : ISODate("2018-09-13T14:06:39.882Z"), "deviceUID" : "f5265ed9-a162-4c72-926d-f537b0ef356c", "value" : 29, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }
{ "_id" : ObjectId("5b9a6eee1284f4000452fdec"), "date" : ISODate("2018-09-13T14:06:38.696Z"), "deviceUID" : "919473a4-b332-4929-9b5e-c0a80f498222", "value" : 25, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }
{ "_id" : ObjectId("5b9a6eee1284f4000452fdeb"), "date" : ISODate("2018-09-13T14:06:38.163Z"), "deviceUID" : "9474a1ee-c1c7-4f1d-a012-c6e4c883c7d3", "value" : 25, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }

我们可以看到,这些都使用相同的网关,因为我们只部署了一个。那么,让我们去在该层中部署另一个pod。我们再次修改JSON中的实例数,然后更新pod配置:

$ dcos marathon pod update mqtt < mqttpod.json Created deployment 1fdc863b-9815-417e-87ac-858b56f8630f Since all of our devices are already attached to the first gateway through the load balanced VIP, let’s increase the device count to 5, and update as above. Once our new devices are up and running, because they are using the load balancer, we should see some of them connect to the new gateway. We can query MongoDB again and see we now have more than one gateway ID in our received data : rs:PRIMARY> db.devices.find().limit(5).sort({$natural:-1})
{ "_id" : ObjectId("5b9a6f981284f4000452fef9"), "date" : ISODate("2018-09-13T14:09:28.076Z"), "deviceUID" : "f5265ed9-a162-4c72-926d-f537b0ef356c", "value" : 26, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }
{ "_id" : ObjectId("5b9a6f971284f4000452fef8"), "date" : ISODate("2018-09-13T14:09:27.158Z"), "deviceUID" : "43e2785e-90b2-4cac-9e68-c3b72984f83c", "value" : 27, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }
{ "_id" : ObjectId("5b9a6f964931e30004900d25"), "date" : ISODate("2018-09-13T14:09:26.942Z"), "deviceUID" : "6b9d763b-699e-47eb-8541-704931dbb6e9", "value" : 26, "gatewayID" : "mqtt.instance-6f0de323-b75e-11e8-9d5d-fe0bc23c90b8.mongogw" }
{ "_id" : ObjectId("5b9a6f961284f4000452fef7"), "date" : ISODate("2018-09-13T14:09:26.882Z"), "deviceUID" : "919473a4-b332-4929-9b5e-c0a80f498222", "value" : 30, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }
{ "_id" : ObjectId("5b9a6f961284f4000452fef6"), "date" : ISODate("2018-09-13T14:09:26.363Z"), "deviceUID" : "9474a1ee-c1c7-4f1d-a012-c6e4c883c7d3", "value" : 26, "gatewayID" : "mqtt.instance-565e6b1f-b75d-11e8-9d5d-fe0bc23c90b8.mongogw" }

最后,我们还可以扩展MongoDB层,通过向我们的副本集添加更多实例来水平扩展读取,或者通过更改实例的大小来纵向扩展读取。出于本演示的目的,我们将另外两个实例添加到我们的副本集中。我们可以通过单击Percona-Server-MongoDB服务,然后单击编辑,然后选择MongoDB选项卡,在DC / OS UI中非常简单地执行此操作:

将计数从3更改为5.一旦我们更改了配置,请单击Review and Run,然后单击Run Service,Percona-Server-MongoDB服务将另外两个实例部署到我们的副本集。

部署完成后,我们将在“服务”选项卡中看到另外两个mongod实例,而不会中断Percona-Server-MongoDB服务本身。

因此,我们可以看到,我们在演示IoT应用程序的每个层中都采用了高度可扩展的架构,而DC / OS使其非常易于部署和管理。随着设备数量的增加,我们可以简单地在我们的负载均衡器后面部署更多的Mosquitto / Gateway pod,如果我们需要在存储层上增加容量或性能,我们可以使用Percona-Server-MongoDB服务轻松扩展MongoDB层要么垂直或水平缩放。您可以在我们的GitHub存储库中找到上面使用的所有代码,以及Dockerfiles和Marathon配置。

原文标题《How to Build a Highly Scalable IoT Platform on DC/OS》

作者:Matt Jarvis

译者:February

不代表云加社区观点,更多详情请查看原文链接

本文系外文翻译,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系外文翻译前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档