目录
-
- 摘要
- 一、MQTT协议概述
-
- [1.1 什么是MQTT](#1.1 什么是MQTT)
- [1.2 MQTT核心概念](#1.2 MQTT核心概念)
- [1.3 QoS等级](#1.3 QoS等级)
- [二、DolphinDB MQTT插件](#二、DolphinDB MQTT插件)
-
- [2.1 插件安装](#2.1 插件安装)
- [2.2 加载插件](#2.2 加载插件)
- [2.3 插件函数](#2.3 插件函数)
- [三、连接MQTT Broker](#三、连接MQTT Broker)
-
- [3.1 基本连接](#3.1 基本连接)
- [3.2 带认证连接](#3.2 带认证连接)
- [3.3 SSL/TLS连接](#3.3 SSL/TLS连接)
- 四、订阅MQTT消息
-
- [4.1 基本订阅](#4.1 基本订阅)
- [4.2 通配符订阅](#4.2 通配符订阅)
- [4.3 消息解析](#4.3 消息解析)
- [4.4 QoS设置](#4.4 QoS设置)
- 五、消息发布
-
- [5.1 基本发布](#5.1 基本发布)
- [5.2 批量发布](#5.2 批量发布)
- [5.3 保留消息](#5.3 保留消息)
- 六、工业物联网实战案例
-
- [6.1 设备数据采集系统](#6.1 设备数据采集系统)
- [6.2 实时数据处理](#6.2 实时数据处理)
- [6.3 数据持久化](#6.3 数据持久化)
- [七、MQTT Broker配置](#七、MQTT Broker配置)
-
- [7.1 EMQX配置](#7.1 EMQX配置)
- [7.2 Mosquitto配置](#7.2 Mosquitto配置)
- [7.3 性能调优](#7.3 性能调优)
- 八、性能优化
-
- [8.1 批量处理](#8.1 批量处理)
- [8.2 多线程处理](#8.2 多线程处理)
- [8.3 消息队列](#8.3 消息队列)
- 九、监控与运维
-
- [9.1 连接状态监控](#9.1 连接状态监控)
- [9.2 错误处理](#9.2 错误处理)
- [9.3 日志记录](#9.3 日志记录)
- 十、最佳实践
-
- [10.1 Topic设计](#10.1 Topic设计)
- [10.2 消息格式](#10.2 消息格式)
- [10.3 性能建议](#10.3 性能建议)
- 十一、总结
- 参考资料
摘要
本文详细介绍DolphinDB与MQTT协议的集成方法,实现物联网设备数据的实时接入。从MQTT协议基础到DolphinDB订阅配置,从消息解析到数据存储,逐步带领读者构建完整的物联网数据采集管道。同时提供工业场景的实战案例和性能优化建议,帮助读者实现高效的实时数据接入。本文适合从事物联网数据采集和处理的工程师阅读。
一、MQTT协议概述
1.1 什么是MQTT
MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,专为物联网场景设计:
MQTT架构
设备1
Publisher
MQTT Broker
设备2
Publisher
设备3
Publisher
订阅者1
DolphinDB
订阅者2
应用服务
订阅者3
监控系统
1.2 MQTT核心概念
| 概念 | 说明 | 示例 |
|---|---|---|
| Broker | 消息代理服务器 | EMQX、Mosquitto |
| Topic | 消息主题 | sensor/temperature/1 |
| Publisher | 消息发布者 | 传感器设备 |
| Subscriber | 消息订阅者 | DolphinDB |
| QoS | 服务质量等级 | 0/1/2 |
1.3 QoS等级
| QoS | 说明 | 适用场景 |
|---|---|---|
| 0 | 最多一次,可能丢失 | 传感器高频数据 |
| 1 | 至少一次,可能重复 | 重要业务数据 |
| 2 | 恰好一次,保证可靠 | 金融交易数据 |
二、DolphinDB MQTT插件
2.1 插件安装
bash
# 下载MQTT插件
cd /opt/dolphindb/server/plugins
git clone https://github.com/dolphindb/DolphinDBPlugin.git
# 编译插件(Linux)
cd DolphinDBPlugin/mqtt
mkdir build && cd build
cmake ..
make
# 插件文件位置
# libPluginMQTT.so
2.2 加载插件
python
// 加载MQTT插件
loadPlugin("/opt/dolphindb/server/plugins/mqtt/libPluginMQTT.so")
// 查看插件函数
getFunctionList()
2.3 插件函数
| 函数 | 说明 |
|---|---|
mqtt::connect |
连接MQTT Broker |
mqtt::subscribe |
订阅主题 |
mqtt::unsubscribe |
取消订阅 |
mqtt::publish |
发布消息 |
mqtt::disconnect |
断开连接 |
三、连接MQTT Broker
3.1 基本连接
python
// 加载插件
loadPlugin("/opt/dolphindb/server/plugins/mqtt/libPluginMQTT.so")
// 连接MQTT Broker
conn = mqtt::connect("tcp://localhost:1883", "dolphindb_client")
// 查看连接状态
print("MQTT连接成功")
3.2 带认证连接
python
// 带用户名密码连接
conn = mqtt::connect(
"tcp://broker.example.com:1883",
"dolphindb_client",
"username",
"password"
)
3.3 SSL/TLS连接
python
// SSL安全连接
conn = mqtt::connect(
"ssl://broker.example.com:8883",
"dolphindb_client",
"username",
"password",
true // 启用SSL
)
四、订阅MQTT消息
4.1 基本订阅
python
// 创建流表接收数据
share streamTable(1:0, `device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE]) as sensor_stream
// 订阅主题
mqtt::subscribe(conn, "sensor/data", sensor_stream)
// 查看接收的数据
select count(*) from sensor_stream
4.2 通配符订阅
python
// MQTT通配符
// + : 单级通配符
// # : 多级通配符
// 订阅所有设备的温度数据
mqtt::subscribe(conn, "sensor/+/temperature", sensor_stream)
// 订阅所有传感器数据
mqtt::subscribe(conn, "sensor/#", sensor_stream)
// 订阅特定车间的所有设备
mqtt::subscribe(conn, "workshop/A/+/data", sensor_stream)
4.3 消息解析
python
// JSON格式消息解析
def parseSensorJson(msg) {
data = parseJson(msg)
return table(
data.device_id as device_id,
data.timestamp as timestamp,
data.temperature as temperature,
data.humidity as humidity
)
}
// 创建带解析的订阅
share streamTable(1:0, `device_id`timestamp`temperature`humidity,
[INT, TIMESTAMP, DOUBLE, DOUBLE]) as sensor_stream
mqtt::subscribe(conn, "sensor/data", sensor_stream, parseSensorJson)
4.4 QoS设置
python
// 设置QoS等级
mqtt::subscribe(conn, "sensor/data", sensor_stream, , 1) // QoS 1
mqtt::subscribe(conn, "alert/critical", alert_stream, , 2) // QoS 2
五、消息发布
5.1 基本发布
python
// 发布消息
mqtt::publish(conn, "sensor/data", '{"device_id":1,"temperature":25.5}')
// 发布到特定主题
mqtt::publish(conn, "device/1/status", "online")
5.2 批量发布
python
// 批量发布消息
def publishBatch(conn, topic, messages) {
for (msg in messages) {
mqtt::publish(conn, topic, toJson(msg))
}
}
// 使用示例
data = table(1..10 as device_id, rand(20..30, 10) as temperature)
publishBatch(conn, "sensor/batch", data)
5.3 保留消息
python
// 发布保留消息(新订阅者会收到最后保留的消息)
mqtt::publish(conn, "device/status", "online", true)
六、工业物联网实战案例
6.1 设备数据采集系统
python
// ========== 1. 创建数据表 ==========
// 实时数据流表
share streamTable(1:0,
`device_id`timestamp`temperature`humidity`pressure`vibration`power`status,
[INT, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, SYMBOL]
) as realtime_stream
// 告警流表
share streamTable(1:0,
`alert_id`device_id`timestamp`alert_type`alert_level`message,
[LONG, INT, TIMESTAMP, SYMBOL, INT, STRING]
) as alert_stream
// ========== 2. 消息解析函数 ==========
def parseDeviceData(msg) {
try {
data = parseJson(msg)
return table(
data.device_id as device_id,
temporalParse(data.timestamp, "yyyy-MM-dd HH:mm:ss.SSS") as timestamp,
double(data.temperature) as temperature,
double(data.humidity) as humidity,
double(data.pressure) as pressure,
double(data.vibration) as vibration,
double(data.power) as power,
data.status as status
)
} catch(ex) {
print("解析错误: " + ex)
return table(1:0, `device_id`timestamp`temperature`humidity`pressure`vibration`power`status,
[INT, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, SYMBOL])
}
}
// ========== 3. 连接并订阅 ==========
// 加载插件
loadPlugin("/opt/dolphindb/server/plugins/mqtt/libPluginMQTT.so")
// 连接Broker
conn = mqtt::connect("tcp://mqtt-broker:1883", "dolphindb_collector")
// 订阅设备数据
mqtt::subscribe(conn, "iot/device/+/data", realtime_stream, parseDeviceData, 1)
// 订阅告警数据
mqtt::subscribe(conn, "iot/alert/#", alert_stream, , 1)
print("MQTT订阅已启动")
6.2 实时数据处理
python
// ========== 4. 创建时间序列引擎 ==========
// 计算每分钟平均值
avg_engine = createTimeSeriesEngine(
"avg_engine",
60000, // 1分钟窗口
60000, // 步长
<[
avg(temperature) as avg_temp,
avg(humidity) as avg_humidity,
avg(pressure) as avg_pressure,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(*) as sample_count
]>,
realtime_stream,
`device_id,
`timestamp
)
// 订阅流表到引擎
subscribeTable(, "realtime_stream", "avg_engine", -1, append!{avg_engine}, true)
// ========== 5. 异常检测引擎 ==========
def detectAnomaly(msg) {
// 温度异常
if (msg.temperature > 35 or msg.temperature < 10) {
alert = table(
now() as alert_id,
msg.device_id as device_id,
msg.timestamp as timestamp,
"temperature" as alert_type,
2 as alert_level,
"温度异常: " + string(msg.temperature) as message
)
alert_stream.append!(alert)
}
// 振动异常
if (msg.vibration > 4.0) {
alert = table(
now() as alert_id,
msg.device_id as device_id,
msg.timestamp as timestamp,
"vibration" as alert_type,
1 as alert_level,
"振动异常: " + string(msg.vibration) as message
)
alert_stream.append!(alert)
}
}
6.3 数据持久化
python
// ========== 6. 数据持久化到分布式表 ==========
// 创建分布式数据库
db = database("dfs://iot_data", COMPO,
[RANGE, 2024.01.01..2024.12.31, VALUE, 1..100])
// 创建分布式表
schema = table(1:0,
`device_id`timestamp`temperature`humidity`pressure`vibration`power`status,
[INT, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, SYMBOL])
db.createPartitionedTable(schema, `sensor_data, `timestamp`device_id)
// 订阅流表,持久化到分布式表
def saveToDistributedTable(msg) {
loadTable("dfs://iot_data", "sensor_data").append!(msg)
}
subscribeTable(, "realtime_stream", "persist", -1, saveToDistributedTable, true, 10000, true)
print("数据持久化已启动")
七、MQTT Broker配置
7.1 EMQX配置
bash
# 安装EMQX
docker run -d --name emqx \
-p 1883:1883 \
-p 8083:8083 \
-p 8084:8084 \
-p 8883:8883 \
-p 18083:18083 \
emqx/emqx:latest
# 访问管理界面
# http://localhost:18083
# 默认账号: admin / public
7.2 Mosquitto配置
bash
# 安装Mosquitto
docker run -d --name mosquitto \
-p 1883:1883 \
-p 9001:9001 \
eclipse-mosquitto
# 配置文件 /mosquitto/config/mosquitto.conf
listener 1883
allow_anonymous true
7.3 性能调优
| 参数 | 建议值 | 说明 |
|---|---|---|
| max_connections | 100000 | 最大连接数 |
| max_message_size | 1MB | 最大消息大小 |
| keepalive | 60s | 心跳间隔 |
| session_expiry | 1h | 会话过期时间 |
八、性能优化
8.1 批量处理
python
// 批量订阅处理
share streamTable(1:0, `device_id`timestamp`value, [INT, TIMESTAMP, DOUBLE]) as batch_stream
// 设置批量大小和超时
mqtt::subscribe(conn, "sensor/batch", batch_stream, , 1, 1000, 5000)
// batchSize=1000, batchTimeout=5000ms
8.2 多线程处理
MQTT Broker
订阅线程1
订阅线程2
订阅线程3
流表1
流表2
流表3
分布式表
8.3 消息队列
python
// 使用消息队列缓冲
def createMQTTQueue(streamName, queueSize=100000) {
// 创建流表
share streamTable(1:0, `data, [STRING]) as streamName
// 创建持久化队列
enableTablePersistence(streamName, true, true, queueSize)
return streamName
}
// 创建队列
createMQTTQueue("mqtt_queue", 1000000)
九、监控与运维
9.1 连接状态监控
python
// 查看订阅状态
getSubscriptionStat()
// 查看流表状态
getStreamStat()
// 查看持久化状态
getPersistenceStat()
9.2 错误处理
python
// 自动重连机制
def connectWithRetry(brokerUrl, clientId, maxRetries=5) {
retryCount = 0
conn = NULL
while (retryCount < maxRetries) {
try {
conn = mqtt::connect(brokerUrl, clientId)
print("MQTT连接成功")
return conn
} catch(ex) {
retryCount += 1
print("连接失败,重试 " + retryCount + "/" + maxRetries)
sleep(5000) // 等待5秒
}
}
throw "MQTT连接失败"
}
// 使用重连
conn = connectWithRetry("tcp://broker:1883", "dolphindb")
9.3 日志记录
python
// 启用调试日志
mqtt::setLogLevel("DEBUG")
// 查看日志
// 日志位置: /opt/dolphindb/server/log/dolphindb.log
十、最佳实践
10.1 Topic设计
| 场景 | Topic格式 | 示例 |
|---|---|---|
| 设备数据 | device/{device_id}/data |
device/123/data |
| 设备状态 | device/{device_id}/status |
device/123/status |
| 告警消息 | alert/{level}/{type} |
alert/high/temperature |
| 批量数据 | batch/{type} |
batch/sensor |
10.2 消息格式
json
// 推荐的JSON消息格式
{
"device_id": 1,
"timestamp": "2024-01-15T10:30:00.123Z",
"data": {
"temperature": 25.5,
"humidity": 50.0,
"pressure": 1013.25
},
"metadata": {
"firmware": "v1.2.3",
"battery": 85
}
}
10.3 性能建议
| 建议 | 说明 |
|---|---|
| 使用QoS 0 | 高频数据可接受少量丢失 |
| 批量发送 | 减少网络开销 |
| 压缩消息 | 减少传输量 |
| 合理分区 | 避免热点Topic |
十一、总结
本文详细介绍了DolphinDB与MQTT协议的集成方法。核心要点如下:
- MQTT协议:轻量级发布/订阅协议,适合物联网场景
- 插件使用:连接、订阅、发布的完整流程
- 消息解析:JSON格式解析和自定义处理
- 实时处理:流表、时间序列引擎、异常检测
- 数据持久化:流表到分布式表的存储
- 性能优化:批量处理、多线程、消息队列
思考题:
- 如何设计Topic结构以支持灵活的数据订阅?
- 如何保证MQTT消息的可靠传递?
- 在高并发场景下如何优化数据接入性能?