产品定价 立即试用
PE MQTT Broker
文档 > MQTT功能 > MQTT over WebSocket
入门
安装 架构 API 常见问题
目录

基于WebSocket的MQTT

前端能力的演进带来了更先进的浏览器功能,显著提升了Web端的用户交互与数据通信。 其中WebSocket是关键:作为一种可靠的通信协议,它重新定义了Web应用中的实时双向通信。

同时,MQTT以其轻量结构和高可靠性著称,尤其适合资源受限、网络不稳定的环境。 该协议已成为IoT生态中消息传输的基石。 其低开销消息传递特性与Web端高效通信需求相契合, 尤其适用于移动设备以及传感器监控、关键通知等需要即时数据交换的场景。

MQTT over WebSocket不仅是技术组合,更是网络通信方式的转变。 它让MQTT消息可直接在浏览器中收发,充分发挥MQTT与WebSocket的优势。 这种结合带来丰富可能:展示实时设备信息、接收实时告警、在移动Web应用中进行高效通信等。

WebSocket简介

WebSocket是一种通信协议,使Web客户端与服务器通过一条长连接实现实时双向通信。 它明显不同于传统HTTP请求/响应模式,支持持续、低延迟的数据交换。 通过HTTP升级握手建立,支持未加密(ws://)和加密(wss://)连接。 WebSocket是需实时内容更新的Web应用的重要基础,提供高效、持久的通信通道。

MQTT over WebSocket的优势

MQTT与WebSocket的结合为Web端IoT应用带来诸多优势。 通过MQTT over WebSocket,传统非Web的MQTT协议可有效延伸到Web应用。 该适配很有必要,因为Web浏览器本身不支持MQTT,需借助WebSocket作为桥梁。

该结合的主要特点包括:

  • 资源利用高效:MQTT为轻量协议,适合带宽或设备能力有限的场景。在WebSocket上使用时,可在Web应用场景下高效利用网络与设备资源。
  • 实时通信:WebSocket提供持久连接,实现低延迟实时数据交换。
  • 双向通信:WebSocket支持全双工,可同时双向传输数据。结合MQTT发布/订阅模型,实现动态、可交互的通信场景。
  • 与Web生态兼容:通过MQTT over WebSocket,协议可与浏览器安全模型兼容,便于接入Web应用,而无需额外插件或特殊配置。
  • 保留MQTT特性:集成不牺牲MQTT原生功能(如保留消息、遗嘱、clean session),保障功能完整可靠。

TBMQ中的MQTT over WebSocket

TBMQ使用WS(WebSocket)和WSS(WebSocket Secure)两个监听器支持WebSocket通信。 可在此查看监听器概览。

文档信息图标

说明:v1.3.0之前的既有部署需更新配置文件以启用WebSocket通信。 例如在AWS部署中,需在AWS负载均衡器上开放额外端口。 请拉取最新配置文件或修改现有配置以应用必要更改。

WebSocket相关参数详情请参阅此处 (查找 LISTENER_WS_ENABLED 及相关环境变量)。

快速开始

本指南演示如何使用 MQTT.js 库连接TBMQ、订阅主题并收发消息的示例。

安装TBMQ

开始前,请确保TBMQ已成功安装。 不同平台安装步骤请参阅安装选项文档。

本指南使用以下快速安装说明。

对于已安装 Docker 的 Linux 或 macOS 用户,建议执行以下命令:

1
2
wget https://raw.githubusercontent.com/thingsboard/tbmq-pe-docker-compose/release-2.2.0/basic/tbmq-install-and-run.sh &&
sudo chmod +x tbmq-install-and-run.sh && ./tbmq-install-and-run.sh

对于已安装 Docker Desktop 的 Windows 用户,建议按以下说明执行。

注意: 请确保下载的 PowerShell 脚本可在您的系统上运行。

  • 打开 PowerShell(以管理员身份运行)。
  • (可选)查看当前执行策略。 它决定了系统上运行脚本的安全级别。例如,若返回 Restricted,表示 PowerShell 不执行任何脚本。
1
Get-ExecutionPolicy
  • (可选)如需,更改当前执行策略。 设置为允许运行 PowerShell 脚本且符合您安全要求的策略。 例如,Unrestricted 为限制最少,允许执行所有脚本。
1
Set-ExecutionPolicy Unrestricted
  • 安装 TBMQ
1
2
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/thingsboard/tbmq-pe-docker-compose/release-2.2.0/basic/windows/tbmq-install-and-run.ps1" `
-OutFile ".\tbmq-install-and-run.ps1"; .\tbmq-install-and-run.ps1

安装MQTT WebSocket客户端

安装MQTT.js前,请确保已安装Node.js运行环境。 安装Node.js可参考此处

安装Node.js后,可使用 npmyarn 安装MQTT.js库。

1
npm install mqtt --save
1
yarn add mqtt

若需全局安装,可使用npm的 -g 参数或yarn的 global 选项。

1
npm install -g mqtt
1
yarn global add mqtt

注意:全局安装可能引发版本冲突,请谨慎使用。

连接客户端

连接选项、订阅主题及发布消息的详细说明请参阅 MQTT.js文档

文档信息图标

说明:用户名 tbmq_websockets_username 对应系统中预置的默认MQTT客户端凭据,专用于WebSocket客户端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
const mqtt = require('mqtt');

const url = 'ws://localhost:8084/mqtt';
const topic = 'sensors/temperature';
const message = 'Hello World';

const options = {
    clean: true,
    clientId: 'tbmq_websockets_client_id',
    username: 'tbmq_websockets_username',
    password: null
};

console.log('Connecting client...');

const client = mqtt.connect(url, options); // connect client

client.on('connect', function () {
    console.log('Client connected!');
    client.subscribe(topic, function (error) { // subscribe to a topic
        if (!error) {
            client.publish(topic, message); // publish a message
        }
    });
});

client.on('message', (topic, message) => { // handle received messages
    console.log(`Received message. Payload: ${message.toString()}. Topic: ${topic}`);
    client.end(); // end client session
});

client.on('error', (error) => { // handle errors
    console.log('Error: ', error?.message);
});

client.on('packetreceive', (packet) => { // handle received packet
    console.log('Packet receive...', packet);
});

client.on('packetsend', (packet) => { // handle sent packet
    console.log('Packet send...', packet);
});

client.on('reconnect', () => {
    console.log('Reconnecting...');
});

client.on('close', () => {
    console.log('Closing client...');
});

请将以上代码保存到名为ws_example.js的文件中,然后执行它。

1
node ws_example.js

上述示例建立了一个WebSocket客户端并连接到TBMQ。 成功连接后,客户端订阅’sensors/temperature’主题。 成功订阅后,客户端向同一主题发布消息。 随后,在收到该消息后,客户端断开连接,有效关闭链接。

以下是执行ws_example.js文件的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
Connecting client...
Packet receive... Packet {
  cmd: 'connack',
  retain: false,
  qos: 0,
  dup: false,
  length: 2,
  topic: null,
  payload: null,
  sessionPresent: false,
  returnCode: 0
}
Client connected!
Packet send... {
  cmd: 'subscribe',
  subscriptions: [ { topic: 'sensors/temperature', qos: 0 } ],
  messageId: 64109
}
Packet receive... Packet {
  cmd: 'suback',
  retain: false,
  qos: 0,
  dup: false,
  length: 3,
  topic: null,
  payload: null,
  granted: [ 0 ],
  messageId: 64109
}
Packet send... {
  cmd: 'publish',
  topic: 'sensors/temperature',
  payload: 'Hello World',
  qos: 0,
  retain: false,
  messageId: 0,
  dup: false
}
Packet receive... Packet {
  cmd: 'publish',
  retain: false,
  qos: 0,
  dup: false,
  length: 32,
  topic: 'sensors/temperature',
  payload: <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>
}
Received message. Payload: Hello World. Topic: sensors/temperature
Packet send... { cmd: 'disconnect' }
Closing client...

此外,你可以使用WebSocket客户端订阅主题并接收消息,以验证结果。

image

连接详情

URL ws://localhost:8084/mqtt由以下几个部分组成:

  • ws://:指定WebSocket协议方案。可以是ws(非加密连接)或wss(加密连接)。
  • localhost:指运行TBMQ的本地机器的主机名。如适用,可替换为DNS主机名。
  • 8084:WebSocket服务器监听传入连接的端口号。
  • /mqtt:TBMQ用于MQTT over WebSocket的必需路径。选择’/mqtt’作为路径是基于MQTT规范。

MQTT over WebSocket Secure (WSS)

在TBMQ中使用MQTT over WebSocket Secure (WSS)为数据提供增强的安全性。 它加密通信,确保设备与broker之间发送的信息免受未授权访问。

在TBMQ中使用MQTT over WebSocket Secure时,理解知名证书颁发机构(CA)签发的证书与自签名证书之间的区别至关重要。 知名CA签发的证书提供更高级别的信任,并被客户端和浏览器广泛认可。 这使其成为面向公众应用的理想选择,因为它们向用户保证连接是安全的,且服务器已通过受信任的权威机构认证。

另一方面,自签名证书可用于内部或测试目的。 虽然它们提供与CA签发证书相同级别的加密,但缺少来自公认CA的信任背书。 这意味着客户端连接到服务器时可能会收到安全警告。 自签名证书对开发或私有网络来说经济实惠,但由于最终用户的信任问题,不建议用于公共或生产环境。

文档信息图标

If you’re utilizing a self-signed certificate for the broker, it’s crucial to manually include it within the browser’s trust store to ensure seamless connectivity. This step is essential for WebSocket client functionality within the browser environment.

总之,为了在TBMQ中获得最大的安全性和用户信任,最好对公共部署使用知名CA签发的证书, 而自签名证书适合内部或开发环境。

双向认证,也称为双向TLS/SSL认证,涉及客户端和服务器通过证书链相互验证身份。 虽然这是一种强健的安全措施,但在浏览器环境中使用WSS实现时会面临挑战。 在典型的浏览器场景中,服务器向客户端出示其证书,浏览器根据受信任CA列表进行验证。 这是标准的单向SSL认证过程。

然而,对于双向SSL认证,客户端还需要向服务器出示证书。 浏览器环境中的挑战在于浏览器并不普遍支持WebSocket连接的客户端证书。 这种支持的缺失源于浏览器安全模型和用户界面的复杂性, 使得无缝实现WSS的客户端证书处理变得困难。 此外,在浏览器环境中管理客户端证书可能很繁琐,并带来用户体验挑战。

因此,虽然双向认证在技术上是可行的且高度安全,但在浏览器中使用WSS的实际实现是有限的,通常不可行。 因此,对于使用WSS的Web应用程序,通常使用单向SSL认证配合额外的安全层(如API密钥或OAuth令牌)来确保安全通信。

在非浏览器环境(如Node.js)以及Python和Java等编程语言中,使用适当的MQTT库时, 双向认证可以无缝运行,仍然是一种非常有效的安全措施。

让我们看看示例。请确保WSS监听器已正确启用和配置

要建立双向认证连接,请确保已创建类型为’X.509 Certificate Chain’的MQTT客户端凭据, 并指定客户端证书的通用名称(CN)。请参阅此指南获取详细说明。 将example.com替换为你的实际DNS,将/path/to/your/client/key/file.pem/path/to/your/client/cert/file.pem/path/to/your/ca/cert/file.pem替换为相应的证书文件路径。

或者,如果你倾向于在以下示例中通过’Basic’凭据(单向认证)进行认证,可以将options.username设置为’tbmq_websockets_username’而不是’null’。 此外,你需要注释掉设置options的行,如’options.key’、’options.cert’以及其他与客户端证书相关的行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
const mqtt = require('mqtt');
const fs = require('fs');

const url = 'wss://example.com:8085/mqtt';
const topic = 'sensors/temperature';
const message = 'Hello World';

// File paths
const keyFile = '/path/to/your/client/key/file.pem';
const certFile = '/path/to/your/client/cert/file.pem';
const caFile = '/path/to/your/ca/cert/file.pem';

const options = {
  clean: true,
  clientId: 'tbmq_websockets_client_id',
  username: null,
  password: null
};

try {
  const dataKey = fs.readFileSync(keyFile);
  const dataCert = fs.readFileSync(certFile);
  const dataCa = fs.readFileSync(caFile);

  // Set the certificate and key options
  options.key = dataKey;
  options.cert = dataCert;
  options.ca = dataCa;
  options.rejectUnauthorized = true;

  console.log('Connecting client...');

  const client = mqtt.connect(url, options); // connect client

  client.on('connect', function () {
    console.log('Client connected!');
    client.subscribe(topic, function (error) { // subscribe to a topic
      if (!error) {
        client.publish(topic, message); // publish a message
      }
    });
  });

  client.on('message', (topic, message) => { // handle received messages
    console.log(`Received message. Payload: ${message.toString()}. Topic: ${topic}`);
    client.end(); // end client session
  });

  client.on('error', (error) => { // handle errors
    console.log('Error: ', error?.message);
  });

  client.on('packetreceive', (packet) => { // handle received packet
    console.log('Packet receive...', packet);
  });

  client.on('packetsend', (packet) => { // handle sent packet
    console.log('Packet send...', packet);
  });

  client.on('reconnect', () => {
    console.log('Reconnecting...');
  });

  client.on('close', () => {
    console.log('Closing client...');
  });

} catch (err) {
  console.error('Error reading certificate file:', err);
}

请将以上代码保存到名为wss_example.js的文件中,然后执行它。

1
node wss_example.js

成功执行wss_example.js文件后,你应该能看到与ws_example.js类似的输出。

总结

在本指南中,我们探讨了MQTT与WebSocket的强大组合,这是一种以高效性和灵活性增强IoT通信的解决方案。 我们深入了解了MQTT over WebSocket如何提供在Web环境中无缝运行的实时双向通信通道,确保数据快速可靠地交换。 在安全性方面,我们讨论了SSL/TLS加密的实现以保障安全数据传输,以及知名CA签发证书与自签名证书的区别。 此外,我们还涉及了实际方面,包括代码示例和浏览器环境中双向认证的限制。 本指南旨在为任何希望实现MQTT over WebSocket的人提供全面的参考资源,确保高效、安全且可靠的IoT通信系统。