☰
Ubuntu 20.04部署EMQX:MQTT物联网消息中间件搭建全攻略
2026/10/7 4:03:46 网站建设 项目流程

接手一个物联网项目,第一步往往是搭消息中间件。手上正好有一台Ubuntu 20.04的服务器,需要跑MQTT服务,我选了EMQX。这篇博客就把从零开始到跑通的完整记录放出来,包括关休眠、换国内源、装EMQX、配账号密码、订阅发布实测,以及排查坑位,按步骤可复现,适合刚接触物联网消息服务的读者。

1. 方案选型与部署架构

1.1 为什么是EMQX而不是Mosquitto

物联网场景下的消息中转,很多人的第一反应是Mosquitto,轻量、单机部署快,学起来一小时就够。但一旦接入的设备量上来,需要集群、规则引擎、数据桥接,Mosquitto就得自己拼一堆插件。我这次选EMQX,核心原因是它把物联网常用的能力全做进了内核:

  • 多协议接入:不止MQTT,还支持MQTT-SN、CoAP、LwM2M,后续如果接非MQTT设备不用再换中间件。
  • 内置规则引擎:可以从消息里提取字段,直接转发到InfluxDB、MySQL、Kafka,省去写转发服务的成本。
  • 集群原生:节点之间自动发现,水平扩展非常平滑。
  • Dashboard可视化:连接数、消息速率、订阅关系一目了然,排障效率比纯命令高得多。

从资源占用来看,EMQX的Erlang/OTP虚拟机确实比Mosquitto吃内存,空闲时约150MB左右,但在2核4G的机器上跑几十台设备完全没压力。如果你只是在校验车上调几个传感器,那Mosquitto足够了;如果想做一个长期运营的物联网平台底座,直接上EMQX,省得后面迁移。

1.2 MQTT协议的三个关键角色

在动手安装前,必须把MQTT的基本模型搞清楚。MQTT里永远有三个角色:

角色作用类比
Broker消息中转中心,就是EMQX邮局
Publisher发送消息的客户端寄信人
Subscriber订阅并接收消息的客户端收信人

三者通过**主题(Topic)**联系起来。比如温湿度传感器发布一条消息到sensor/room1/temp,监控大屏订阅了这个主题,就能实时收到数据。MQTT的订阅支持通配符,sensor/+/temp匹配所有房间的温度,#匹配多层级所有主题,这是MQTT最灵活的地方。

还有两个关键机制:QoS(服务质量)和遗嘱消息(Last Will)。QoS 0最快但可能丢消息,QoS 1至少一次但可能重复,QoS 2恰好一次但性能最差。我在实际项目里默认用QoS 1,其次是QoS 0。遗嘱消息则是设备断线时由Broker替它广播一条“我挂了”的消息,这是做设备在线监控的利器,后面配置账号时会提怎么验证。

1.3 版本选择与资源规划

这一版选EMQX很关键。目前官方提供的版本主要有4.x和5.x两条线:

  • EMQX 4.x:经典版,文档丰富,网上教程多,插件机制熟悉,很多老项目还在用。
  • EMQX 5.x:当前主力,Dashboard改版大,配置支持HOCON格式,Dashboard操作更顺手,资源占用优化明显。

新项目建议直接上5.x,我这里用的是5.8的社区版(Open Source版)。社区版足够支持生产级单机部署,只有集群管理、热配置等企业功能被限制,个人学习和小规模商用没问题。

资源规划方面,在Ubuntu 20.04上跑EMQX最低配1核1G也能启动,但建议至少2核2G,磁盘留10GB以上用于日志和消息堆积。我测试机是2核4G,实测连接200个客户端、每秒500条消息时CPU占用约20%,内存约500MB,完全扛得住。

2. 环境准备与Ubuntu基础调优

2.1 关闭休眠功能避免部署中断

这是Ubuntu 20.04服务器部署最容易踩的坑。默认桌面版Ubuntu会挂起系统,服务器长时间SSH操作后突然断连,多半是休眠触发了。

Ubuntu 20.04使用的是systemd管理电源状态,先检查当前休眠配置:

systemctl status sleep.target suspend.target hibernate.target hybrid-sleep.target

如果状态不是inactive,直接禁用:

sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

mask和disable的区别要理解一下。disable只是取消开机启动,系统仍然可以通过其他方式触发休眠;mask则是彻底屏蔽,连手动执行的入口都堵死。服务器场景必须用mask。

另外还要检查桌面环境自带的电源管理设置,GNOME桌面的设置在“设置”-“电源”里把“自动挂起”改为“从不”。如果用的是最小化服务器版没有桌面,只需上面的systemctl命令就够了。

还有一个细节:禁用休眠后,建议同时修改SSH断连保护参数,防止临时掉线导致安装中断。编辑/etc/ssh/sshd_config,找到ClientAliveInterval和ClientAliveCountMax,改为:

ClientAliveInterval 60 ClientAliveCountMax 3

这样SSH每60秒发一次心跳包,允许连续3次超时,180秒内网络抖动不会断开连接。

2.2 换用国内源加速安装更新

Ubuntu 20.04官方源在国内有时速度感人,安装依赖可能要等几分钟。这里直接把软件源替换为阿里云镜像。先备份原配置:

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

然后编辑/etc/apt/sources.list:

sudo sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list sudo sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list

如果之前用的是清华源之类,想统一替换也更简单,直接清空文件写入:

deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse

写完后刷新索引:

sudo apt update sudo apt upgrade -y

顺手装上后续排查会用到的工具:

sudo apt install -y net-tools curl wget nano mosquitto-clients

mosquitto-clients这一步很多人会忽略。它自带mosquitto_pub和mosquitto_sub命令行工具,测试MQTT消息发布订阅非常方便,不用专门开IDE写测试代码。

2.3 防火墙与端口放行

EMQX默认占用下面几个端口,部署前要规划好防火墙策略:

端口用途
1883MQTT TCP协议端口
8883MQTT TLS/SSL加密端口
8083WebSocket端口,浏览器场景用
8084WSS加密WebSocket端口
18083Dashboard管理控制台端口
4370集群节点间通信端口

如果启用了ufw防火墙,需要放行这些端口。只放行生产必要的端口:

sudo ufw allow 1883/tcp sudo ufw allow 18083/tcp sudo ufw allow 8083/tcp sudo ufw status

注意:如果是云服务器,光改系统防火墙还不够,必须同步在云控制台的安全组里放行端口。我遇到过本地ufw全开放了,但外网死活连不上的情况,最后发现是云安全组默认只放行22端口,这个问题很多新手会忽略。

测试期间如果图省事可以临时关闭防火墙,但生产环境务必保持开启,并且只放行必要端口。

3. EMQX安装与基础配置

3.1 通过APT仓库安装

官方提供两种安装方式:APT仓库和Docker。先讲APT方式,这是最推荐的生产部署方式,配置管理、日志、systemd服务都走标准路径。

EMQX提供了专门的APT仓库,安装时先导入仓库信息:

# 安装基础工具 sudo apt update sudo apt install -y curl gnupg apt-transport-https # 添加EMQX官方GPG密钥 curl -fsSL https://packages.emqx.net/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/emqx.gpg # 添加APT源 echo "deb [signed-by=/usr/share/keyrings/emqx.gpg] https://packages.emqx.net/emqx-ce/deb/ubuntu focal main" | sudo tee /etc/apt/sources.list.d/emqx.list # 刷新源并安装 sudo apt update sudo apt install -y emqx

关于codename有个细节:EMQX的APT源对20.04用focal,18.04用bionic,22.04用jammy,别写错,不然后面依赖解析会出问题。

启动服务并设置开机自启:

sudo systemctl start emqx sudo systemctl enable emqx systemctl status emqx

看到active (running)就说明安装成功。安装完后,默认Dashboard地址是http://你的服务器IP:18083,默认管理员账号密码是admin/public,首次登录会强制要求修改密码。

再验证一下MQTT端口是否在监听:

sudo netstat -tlnp | grep 1883 tcp6 0 0 :::1883 :::* LISTEN 12345/beam.smp

看到1883端口监听就对了。这里的进程名是beam.smp,EMQX底层Erlang虚拟机的进程名,看到这个不用慌。

3.2 Docker方式对比参考

如果你的服务器上已经跑了不少Docker容器,用Docker部署EMQX也不差,对隔离环境尤其方便:

# 拉取并启动容器 docker run -d --name emqx \ -p 1883:1883 \ -p 8083:8083 \ -p 18083:18083 \ -e EMQX_DASHBOARD__DEFAULT_PASSWORD=你的密码 \ emqx/emqx:5.8

Docker方式的限制主要在配置持久化上。容器内/opt/emqx/data是数据目录,必须挂载到宿主机:

docker run -d --name emqx \ -p 1883:1883 -p 8083:8083 -p 18083:18083 \ -v emqx-data:/opt/emqx/data \ -v emqx-log:/opt/emqx/log \ emqx/emqx:5.8

否则容器一删配置全丢。这个坑我踩过,升级EMQX版本后直接照搬老容器配置没挂数据卷,所有用户、规则引擎、认证设置全部重置,教训极其惨痛。

个人还是更喜欢APT方式,因为升级用apt upgrade emqx就行,配置路径固定,排查文档也好对。Docker适合快速体验和多套环境隔离,生产环境建议二选一后保持统一。

3.3 Dashboard初始化与基本设置

通过浏览器访问http://IP:18083,第一次登录会看到初始化界面。这里要做的核心事情就一件:改掉默认管理员密码。

登录后进入 Dashboard,每个版本的界面可能有差异,但设置逻辑一致:

  • 左侧菜单找“管理”-“用户管理”,修改admin用户的密码。
  • 确认版本号与节点状态正常,默认只有一个节点,状态为Running。
  • 检查系统内存和连接数指标,确认无异常报警。

Dashboard右上角能看到当前连接数、订阅数、消息流入流出速率,这四个数字是判断服务是否健康的第一抓手。心跳正常但消息收发为0,大概率是订阅主题不匹配;消息流入有数值但流出为0,一般是订阅端没有连上来。这种监控视角比看日志快得多。

提示:如果18083端口无法访问,先本地curl试一下:curl -I http://127.0.0.1:18083。本机能通外网不通,查防火墙和安全组;本机都不通,查emqx服务状态和端口监听。

4. 账号密码与访问控制配置

4.1 内建认证添加用户

EMQX刚装好时MQTT客户端可以匿名连接,生产环境必须关掉。我选择用内置数据库认证(Built-in Database),不需要额外依赖,配置简单。

在Dashboard左侧菜单进入“访问控制”->“认证”,点击“创建”按钮:

  • 认证方式:选择“密码认证”(Password-Based)
  • 后端类型:选择“内置数据库”(Built-in Database)
  • 数据源:默认选中“内置数据库”即可
  • 保存后全局认证即启用

然后在“访问控制”-“用户管理”里“添加用户”,填入客户端ID和密码。这里有个常见误区:EMQX的用户名(Username)和MQTT的Client ID是两个概念。Username是认证凭据,Client ID是连接标识,两者可以相同,也可以不同。规则引擎处理时,通常两侧都能拿到。

我实际项目中习惯按设备类型规划用户名,比如device_temp_001、gateway_485_01,密码生成随机串并写入设备端配置。注意,EMQX的密码不支持明文直接入库,5.x版本会自动使用BCrypt算法做哈希,创建用户时只需要填明文密码,系统自动加盐处理。

配置完成后,需要再确认“认证”页面里的状态是启用。另外每添加一个用户后建议点一次“测试”按钮,用刚配置的账号密码测试连接是否通过,避免设备端配错了才排查。

4.2 客户端连接与验证

配置完账号后,立即用命令行验证,不要等设备接入才发现问题。使用前面装的mosquitto-clients工具:

# 订阅一个测试主题 mosquitto_sub -h 127.0.0.1 -p 1883 -u device_temp_001 -P '密码' -t 'test/topic' -v # 另开一个终端,发布消息 mosquitto_pub -h 127.0.0.1 -p 1883 -u device_temp_001 -P '密码' -t 'test/topic' -m '{"temp":25.6}'

订阅端收到JSON消息就说明整条链路通了。这里两个工具没加--debug参数,如果连不上,建议加上-d参数看完整交互过程:

mosquitto_sub -d -h 127.0.0.1 -p 1883 -u device_temp_001 -P '密码' -t 'test/topic'

如果看到Connection Refused: not authorised,说明用户名密码不对,或者认证配置没生效。如果看到Connection Refused: connection refused,则是服务没起来或端口错。

再验证一下匿名是否已被拦截。故意不带用户名和密码连接:

mosquitto_pub -h 127.0.0.1 -p 1883 -t 'test/topic' -m 'no auth'

这条命令应该报错,因为认证已经启用。如果它成功发出了,说明认证配置没有真正生效,去Dashboard检查全局认证状态是否为启用。

还有遗嘱消息的验证。发布端指定遗嘱后强制断开:

mosquitto_pub -h 127.0.0.1 -p 1883 -u device_temp_001 -P '密码' -t 'device/status' -m '{"online":true}' --will-topic 'device/status' --will-payload '{"online":false}' --will-qos 1

订阅device/status的终端会在publish端断开后收到{"online":false},这就是设备离线检测的基础,和485设备网关对接时会经常用到这个机制。

5. MQTT订阅发布消息实战与场景扩展

5.1 对接485设备的数据读取与指令下发

MQTT最常见的物联网落地场景就是采集Modbus RTU设备数据,再让上层应用通过MQTT下发控制指令。整个链路是:

485设备 <-> Modbus网关 <-> MQTT Broker (EMQX) <-> 数据平台/业务系统

Modbus网关通常支持MQTT直接上报数据。以我手里的某款网关为例,它配置了MQTT连接参数后,会自动将Modbus寄存器数据发布到主题gateway/device1/data,载荷格式类似:

{"register":40001,"value":156,"timestamp":1699950000}

平台侧订阅该主题即可实时入库。指令下发时,平台向gateway/device1/command主题发布消息:

{"register":40003,"value":1,"action":"write_single"}

网关收到后会解析指令并转为Modbus写操作,回复结果再发布到gateway/device1/response。这套模式的关键在于:消息格式必须前端先行约定,寄存器地址、字节顺序、数据类型都要在协议文档里写死,否则上线后联调会非常痛苦。

Kingscada这类组态软件也是走同样的套路。Kingscada自带的MQTT客户端插件,本质就是一个Subscriber,配置好Broker地址、Topic格式、JSON节点映射,就能把MQTT数据拉进组态画面。对应的订阅主题和字段映射规则,必须在EMQX侧先创建一个测试账号,然后用mosquitto_pub模拟设备发一条完整报文给Kingscada端验证字段是否对齐。

5.2 使用MQTTX图形化工具调试

命令行工具验证链路没问题后,建议再装一个MQTTX。这是目前最好用的MQTT客户端调试工具,支持跨平台,配置文件可导出:

  • 新建连接:填入EMQX的IP、端口、Username、Password。
  • 添加订阅:填写test/topic,点击订阅,消息列表会实时显示。
  • 发布消息:Payload可以选JSON格式,支持格式化展示,非常直观。

用MQTTX的好处是能在同一界面同时管理多个连接,模拟多个设备并行测试。我在测试多设备并发时,会开三四个MQTTX连接,分别用不同的账号和Topic标签来模拟不同房间的设备,比命令行切换终端高效很多。

MQTTX还有个特性是可以通过WebSocket连接EMQX的8083端口。这对应浏览器中的MQTT over WebSocket场景,如果之后要做网页版设备监控大屏,这个能力后面直接用得上。

5.3 规则引擎转发数据(扩展知识)

5.x版本里,规则引擎替代了4.x的数据桥接插件。在做数据落库时,Dashboard左侧“规则”-“创建规则”里填SQL,例如:

SELECT payload.temp as temp, payload.humidity as humidity, clientid as client_id, timestamp as ts FROM "test/topic" WHERE payload.temp > 30

这里的SQL语法类似但并非标准SQL,FROM后跟的是订阅主题,payload提取用点号语法。规则创建后要接一个“动作”,比如保存到MySQL。这个方向如果展开篇幅很大,这里只提个思路:规则引擎可以实现“温度超过阈值自动告警”“数据实时入库”等效果,是EMQX相比Mosquitto的最大优势。

6. 常见问题与排查技巧实录

6.1 典型问题速查表

把部署到现在遇到的典型问题整理成一张表,方便对照处理:

故障现象可能原因排查方法
服务启动失败端口被占用sudo netstat -tlnp | grep 1883
Dashboard无法访问防火墙/安全组未放行18083本地curl测试,再查防火墙配置
客户端连接被拒绝未启用认证或账号密码错误mosquitto_sub -d查看报错信息
客户端认证失败密码哈希算法不匹配Dashboard重新创建用户
订阅收不到消息Topic不通配或QoS不匹配检查主题字符串是否完全一致
消息发不出去QoS为0且网络抖动丢消息升级QoS级别或检查网络质量
连接数满了默认配置了最大连接数Dashboard查看连接数与系统限制
搭建好无法外网访问云平台安全组未放行登录云控制台检查安全组规则

6.2 收不到消息的排查思路

“收不到消息”是MQTT排查里最常见的问题。我处理这类问题有一套固定检查顺序:

  1. 连接是否成功:在订阅端和发布端都加-d参数看是否CONNECT成功。
  2. 主题是否精确一致:MQTT对大小写敏感,Test/topic和test/topic是两个完全不同的主题。
  3. 通配符是否按预期工作:sensor/#能匹配sensor/room1/temp,但sensor/#/temp是无效语法,注意#只能出现在最后。
  4. QoS传递逻辑:发布QoS为0,即使订阅端请求QoS 2,最多收到QoS 0消息;发布QoS 2、订阅QoS 1时,消息按QoS 1投递。两边协商取最小值。
  5. 认证权限:确保订阅账号具有订阅该主题的权限,有些认证配置了ACL但忘记给新账号加读写权限。

其中第4点是原理性知识,最容易忽略但每次都让人抓狂。建议在测试阶段固定发布端和订阅端都是QoS 1,避免混用引起的“伪丢消息”现象。

6.3 我的几条独家避坑经验

经验一:日志要会看两个地方

EMQX出问题时,第一现场在/var/log/emqx/emqx.log,第二现场是Dashboard的“监控”页面。日志级别默认是warning,如果怀疑数据层面有问题,可以在配置文件里临时把日志级别调成debug,排查完再改回来。调日志对性能有一定影响,生产环境谨慎操作。

经验二:升级版本前先备份数据目录

EMQX配置和用户数据都在/opt/emqx/data下。升级前先tar czf emqx-data.tar.gz /opt/emqx/data,升级后如果Dashboard里的用户不见了,直接用备份恢复整个目录。血的教训,别问怎么知道的。

经验三:不要用默认密码跑生产

EMQX安装后默认账号密码是admin/public,很多人装完顺手改一下Dashboard密码就觉得万事大吉。实际上MQTT客户端这一层是一个独立的认证体系,Dashboard的管理员密码只保护网页控制台,设备连接是用认证里创建的用户名密码,两层一定要分别设置强度足够的密码。

经验四:时间不同步先修时钟

EMQX的TLS证书校验和遗嘱消息都依赖系统时间。遇到莫名其妙连接失败、证书报错,先执行date看系统时间是否准确。Ubuntu服务器默认可能没装NTP,建议一开始就同步好:

sudo apt install -y ntpdate sudo ntpdate ntp.aliyun.com

经验五:日志别存根目录

EMQX默认日志存储位置是/opt/emqx/log,运行时间长了日志增长很快。建议做日志轮转限制,或者在磁盘规划时为/opt单独分区。不然日志写满根分区,整个系统都会出现各种诡异问题,这是运维阶段最容易炸掉的雷。

在Ubuntu 20.04上搭建EMQX,整体流程比我预想的顺滑,从装环境到跑通订阅发布,一个下午就能完成。最花时间的部分是理解MQTT的订阅和发布模型,以及认证配置的逻辑。把这套基础打牢后,后面接设备、做规则引擎、对接数据平台,都是在现有框架上添加能力的环节,踩坑概率大大降低。如果只是个人学习和设备量不大的场景,社区版EMQX配合这笔记里的配置完全够用,等后面设备量超过千台再考虑集群方案也不迟。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询