1. MQTT网关基础架构搭建
任务目标
搭建一个最小可运行的MQTT网关,实现MQTT Broker与客户端之间的双向消息转发,并验证基本通信功能。本案例使用Node.js与MQTT.js实现,网关作为中间层连接Broker与客户端,演示消息的订阅与发布转发链路。
环境依赖
- Node.js 18+
- npm包:
mqtt(MQTT.js客户端库) - 可用的MQTT Broker(本案例使用公共测试Broker:
broker.emqx.io:1883)
实现代码
创建 gateway.js,完整代码如下:
const mqtt = require('mqtt');
// 网关配置
const BROKER_URL = 'mqtt://broker.emqx.io:1883';
const TOPIC_IN = 'gateway/+/in'; // 客户端上报主题(通配订阅)
const TOPIC_OUT = 'gateway/+/out'; // 网关下发主题
// 创建网关与Broker的连接
const gateway = mqtt.connect(BROKER_URL, {
clientId: 'mqtt_gateway_' + Math.random().toString(16).substr(2, 8),
clean: true
});
gateway.on('connect', () => {
console.log('[网关] 已连接Broker:', BROKER_URL);
// 订阅所有客户端上报主题
gateway.subscribe(TOPIC_IN, { qos: 1 }, (err) => {
if (err) {
console.error('[网关] 订阅失败:', err.message);
process.exit(1);
}
console.log('[网关] 已订阅:', TOPIC_IN);
});
});
// 消息转发核心逻辑
gateway.on('message', (topic, payload) => {
// 解析主题:gateway/{clientId}/in
const parts = topic.split('/');
if (parts.length !== 3 || parts[2] !== 'in') {
return; // 非预期主题,忽略
}
const clientId = parts[1];
const message = payload.toString();
console.log(`[网关] 收到来自 ${clientId} 的消息: ${message}`);
// 转发到对应的下发主题
const outTopic = `gateway/${clientId}/out`;
gateway.publish(outTopic, message, { qos: 1 }, (err) => {
if (err) {
console.error('[网关] 转发失败:', err.message);
} else {
console.log(`[网关] 已转发到 ${outTopic}`);
}
});
});
// 错误处理
gateway.on('error', (err) => {
console.error('[网关] 连接错误:', err.message);
process.exit(1);
});
// 优雅退出
process.on('SIGINT', () => {
console.log('\n[网关] 正在关闭...');
gateway.end(true);
process.exit(0);
});
运行与验证
1. 安装依赖并启动网关:
npm init -y
npm install mqtt
node gateway.js
预期输出(示例):
[网关] 已连接Broker: mqtt://broker.emqx.io:1883
[网关] 已订阅: gateway/+/in
2. 验证消息转发(需另开两个终端):
终端A——模拟客户端发布消息:
node -e "const mqtt=require('mqtt');const c=mqtt.connect('mqtt://broker.emqx.io:1883',{clientId:'test_client'});c.on('connect',()=>{c.publish('gateway/test_client/in','Hello Gateway',{qos:1},()=>{console.log('已发布');c.end();});});"
终端B——模拟客户端订阅下发主题:
node -e "const mqtt=require('mqtt');const c=mqtt.connect('mqtt://broker.emqx.io:1883',{clientId:'sub_client'});c.on('connect',()=>{c.subscribe('gateway/test_client/out',{qos:1},()=>{console.log('已订阅');});});c.on('message',(t,p)=>{console.log('收到转发消息:',p.toString());c.end();process.exit(0);});"
3. 通过条件:
- 网关终端显示收到来自
test_client的消息并成功转发; - 终端B打印出
收到转发消息: Hello Gateway; - 三个终端均无错误输出。
常见问题
- 连接失败:公共Broker可能不稳定,可更换为本地Broker(如Mosquitto,地址改为
mqtt://localhost:1883)。 - 消息未转发:确认发布主题严格匹配
gateway/{clientId}/in格式,且clientId与订阅端期望的一致。