1. MQTT网关基础架构搭建

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与订阅端期望的一致。