1 实现方法
- 安装EMQ
- 配置nginx转发
- 代码测试
1 安装EMQ
- 1.1 采用docker安装,传送门
docker pull emqx/emqx:v4.0.0
docker run -d --name emqx -p 1883:1883 -p 8081:8081 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx/emqx:v4.0.0
- 1.2 EMQ X SSL/TLS 使用配置指南
如果客户端需要直接与 EMQ X 建立 SSL/TLS 连接,那么需要修改 EMQ X 中 SSL/TLS 相关的配置项,通常包括监听端口、CA 证书文件、服务器证书文件等。
如果图省事,可以直接使用emq自带的证书
官方链接:EMQ X SSL/TLS 使用配置指南 | EMQ
# 监听端口我们使用默认的 8883
listener.ssl.external = 8883
# 配置为我们申请下来的证书
listener.ssl.external.keyfile = etc/certs/zhouzb.club/Apache/3_zhouzb.club.key
listener.ssl.external.certfile = etc/certs/zhouzb.club/Apache/2_zhouzb.club.crt
listener.ssl.external.cacertfile = etc/certs/zhouzb.club/Apache/1_root_bundle.crt
# 不开启对端验证
listener.ssl.external.verify = verify_none
- 1.3 配置文件说明 官方链接:配置说明 | EMQ Docs (emqx.cn) 配置文件 | 说明 | | ------------------ | ------------------- | | etc/emqx.conf | EMQ X 配置文件 | | etc/acl.conf | EMQ X 默认 ACL 规则配置文件 | | etc/plugins/*.conf | EMQ X 扩展插件配置文件|
2 配置nginx转发
为什么要配置nginx转发,其实这里有两个好处:
- 一是用nginx可以分流,避免流量高峰
- 二是nginx的高级用法,可以将非加密连接转发到加密连接中
server {
# 建议 WebSocket 也绑定到 443 端口
#listen 443, 8083;
listen 443 ssl;
server_name your.site.com;
ssl on;
ssl_certificate ssl/your.pem; # 证书路径
ssl_certificate_key ssl/your.key; # 密钥路径
location /mqtt {
proxy_pass http://127.0.0.1:8084;
proxy_set_header Sec-WebSocket-Protocol mqtt;
# 这行就是去除 Sec-WebSocket-Protocol
#more_clear_headers Sec-WebSocket-Protocol;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection "upgrade";
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
3 代码测试
这里直接使用mqttjs库连接, 使用前请自行下载.
const mqtt = require('mqtt')
const fs = require('fs')
const { Command } = require('commander')
const program = new Command()
program
.option('-p, --protocol <type>', 'connect protocol: mqtt, mqtts, ws, wss. default is mqtt', 'mqtt')
.parse(process.argv)
const host = 'test.mosquitto.org'
const port = '1883'
const clientId = `mqtt_${Math.random().toString(16).slice(3)}`
// connect options
const OPTIONS = {
clientId,
clean: true,
connectTimeout: 4000,
username: 'emqx',
password: 'public',
reconnectPeriod: 1000,
}
// protocol list
const PROTOCOLS = ['mqtt', 'mqtts', 'ws', 'wss']
program.protocol = "wss"
// default is mqtt, unencrypted tcp connection
let connectUrl = `mqtt://${host}:${port}`
if (program.protocol && PROTOCOLS.indexOf(program.protocol) === -1) {
console.log('protocol must one of mqtt, mqtts, ws, wss.')
} else if (program.protocol === 'mqtts') {
// mqtts, encrypted tcp connection
connectUrl = `mqtts://${host}:8883`
// OPTIONS['ca'] = fs.readFileSync('./broker.emqx.io-ca.crt')
} else if (program.protocol === 'ws') {
// ws, unencrypted WebSocket connection
const mountPath = '/mqtt' // mount path, connect emqx via WebSocket
// connectUrl = `ws://${host}:8080${mountPath}`
connectUrl = `ws://${host}:8080`
} else if (program.protocol === 'wss') {
// wss, encrypted WebSocket connection
const mountPath = '/mqtt' // mount path, connect emqx via WebSocket
connectUrl = `wss://test.mosquitto.org:443/mqtt`
} else {}
console.log("connectUrl:"+connectUrl);
const topic = '/msg/alarmUser/1397739313621377025'
const client = mqtt.connect(connectUrl, OPTIONS)
client.on('connect', () => {
console.log(`${program.protocol}: Connected`)
client.subscribe([topic], () => {
console.log(`${program.protocol}: Subscribe to topic '${topic}'`)
})
client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false }, (error) => {
if (error) {
console.error(error)
}
})
})
client.on('reconnect', (error) => {
console.log(`Reconnecting(${program.protocol}):`, error)
})
client.on('error', (error) => {
console.log(`Cannot connect(${program.protocol}):`, error)
})
client.on('message', (topic, payload) => {
console.log('Received Message:', topic, payload.toString())
})