业务背景:
开发一个叫号系统,需要实现客户端与服务端可以实时通信(接受叫号、就诊等一系列信号),在客户端下线时告知服务端,结束连接、释放进程。
MQTT对比websocket:
这两者的异同及使用场景大家可以参考此博客:mqtt对比websocket
当然,在web开发中使用mqtt其实也是mqtt over websocket模式的,使用mqtt的原因则主要是mqtt具有消息等级(qos)、上线、遗嘱等一系列功能,更贴合业务需要。
实际运用:
在这之前,如果你对mqtt还不是很了解,并没有简单上手,可以参考此文档:
MQTT 最全教程:从入门到精通 | EMQ (emqx.com)
mqttjs的github链接:https://github.com/mqttjs/MQTT.js
常用api(详细的请查阅mqttjs的github):
- mqtt.connect([url], options)
options常用属性如下:
wsOptions
: is the WebSocket connection options. Default is{}
keepalive
:60
seconds, set to0
to disable
clientId
:'mqttjs_' + Math.random().toString(16).substr(2, 8)
protocolId
:'MQTT'
protocolVersion
:4
clean
:true
, set to false to receive QoS 1 and 2 messages while offline
reconnectPeriod
:1000
milliseconds, interval between two reconnections. Disable auto reconnect by setting to0
connectTimeout
:30 * 1000
milliseconds, time to wait before a CONNACK is received
username
: the username required by your broker, if any
password
: the password required by your broker, if any
properties
: properties MQTT 5.0.object
that supports the following properties:
sessionExpiryInterval
: representing the Session Expiry Interval in secondsnumber
,userProperties
: The User Property is allowed to appear multiple times to represent multiple name, value pairsobject
,will
: a message that will sent by the broker automatically when the client disconnect badly
topic
: the topic to publishpayload
: the message to publishqos
: the QoSretain
: the retain flagproperties
: properties of will by MQTT 5.0
willDelayInterval
: representing the Will Delay Interval in secondsnumber
userProperties
: The User Property is allowed to appear multiple times to represent multiple name, value pairsobject
实际运用中,基本功能可以参照官方demo,我们可以根据需要做一些完善:
1、多环境配置
不同环境连接的MQTT Broker是不同的,mqtt在https的情况下需要使用的是wss协议,我们可以把不同的url、协议、用户名等等挂载到process上实现此效果。
2、循环订阅及接收主题
在data中声明需要订阅的主题及信息
list = [{name:`queue/clear-data`, qos: 1, method: this.reset, noArgument: true}]
在连接成功时循环订阅此列表,并在接收消息时根据配置项调用对应方法
// 订阅
doSubscribe() {
this.subcribeList.forEach(item => {
if (!this.client.subscribe) return
this.client.subscribe(item.name, { qos: item.qos }, (error, res) => {
if (error) {
return
}
})
})
}
// 接收
this.client.on('message', (topic, message) => {
this.subcribeList.forEach(item => {
if (item.name === topic) {
item.noArgument ? item.method() : item.method(JSON.parse(message))
}
})
})
遇到的坑
1、因为使用mqtt5,所以我把mqtt版本升级到了5.1.4,发现mqtt的connect导入报错,查看对应版本的源码后发现,这个方法是分块导出,代码应该为 import { connect } from 'mqtt'
2、已经升级为mqtt5了,但是mqtt5的新功能却怎么也使用不了,后来发现protocolVersion
这个配置项居然有默认值,并且是4,需要手动去改成5!!!