Apache BifroMQ 3.3.5 安装指南

Apache BifroMQ 3.3.5 安装指南:Ubuntu 22.04 从零安装单机版,涵盖 JDK 17 前置、官方包 sha256 校验、启停、MQTT 收发与 REST 验证、systemd 托管及 JVM 堆调优,均实测

Apache BifroMQBifroMQ2026/10/13

Apache BifroMQ 3.3.5 安装指南

目标:在 Ubuntu 22.04 服务器上从零安装 Apache BifroMQ 3.3.5 单机版(standalone),覆盖 OpenJDK 17 前置、官方发行包下载与 sha256 校验、目录部署、服务启停、MQTT 连通与基础收发验证(QoS0/QoS1/保留消息)、REST API 验证、systemd 托管及 JVM 堆 256-512MB 调优。以下命令与回显均在 Ubuntu 22.04.5 真实环境逐步实测。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Java:OpenJDK 17.0.20.1(openjdk-17-jdk-headless,BifroMQ 硬性要求 JDK 17+)
  • Apache BifroMQ:3.3.5(官方 standalone 二进制发行包,126,286,685 字节 ≈ 120MB)
  • 安装目录:/usr/share/bifromq
  • 数据目录:/usr/share/bifromq/data(启动时自动创建,RocksDB 引擎)
  • 日志目录:/usr/share/bifromq/logs(启动时自动创建)
  • 服务端口:MQTT TCP 1883、MQTT over WebSocket 8080、HTTP 管理 API 8091、Prometheus 指标 9090
  • 客户端工具:mosquitto-clients 2.0.11(mosquitto_pub/mosquitto_sub)
  • 运行用户:root

💡 说明:BifroMQ 是 Apache 顶级候选的分布式 MQTT 消息中间件(源自百度,2024 年进入 Apache 孵化器,现已毕业),单机版开箱即用:内置 basekv 分布式存储(RocksDB 引擎)承载会话、订阅与保留消息,无需任何外部数据库或注册中心。

二、前置条件

  • 一台 Ubuntu 22.04 服务器,root 权限。
  • 磁盘:安装包约 120MB,解压后约 300MB,另为数据目录预留 2GB 以上。
  • ⚠️ /tmp 必须可执行:BifroMQ 启动时会把 netty 原生库(libnetty_transport_native_epoll)解压到 /tmp 并加载执行,若 /tmp 挂载了 noexec 选项,MQTT 订阅会异常(SUBACK 返回 128),详见「常见问题」。
  • 工具包:wget、curl、net-tools(含 netstat)、procps(含 jps)、mosquitto-clients。

三、版本选型说明

Apache BifroMQ 的发布渠道随大版本变化,截至本文实测(2026-10):

版本线最新版本二进制获取渠道说明
4.x4.0.0-incubating(2026-01-28)downloads.apache.org4.x 与 3.x 不兼容,二进制不在 GitHub Releases 挂资产
3.x3.3.5(2025-02-25)GitHub Releases本文采用;GitHub 资产可直接 wget

通过 GitHub API 核实(节选):

v4.0.0-incubating | prerelease: False | 2026-01-28   (无 GitHub 二进制资产)
v3.3.5 | prerelease: False | 2025-02-25
   asset: bifromq-3.3.5-standalone.tar.gz 126286685
   asset: bifromq-3.3.5-windows-standalone.zip 126328405

⚠️ 仓库迁移坑:项目原地址 bifromq/bifromq 已迁移为 apache/bifromq,老链接 https://github.com/bifromq/bifromq/releases/download/... 会 404,请使用新地址。

3.3.5 提供两个二进制资产:

制品说明
bifromq-3.3.5-standalone.tar.gzLinux 单机版发行包(本文采用)
bifromq-3.3.5-windows-standalone.zipWindows 单机版

四、安装步骤

4.1 安装 JDK 17 与基础工具

apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y \
    openjdk-17-jdk-headless wget curl net-tools procps mosquitto-clients

验证版本回显:

java -version
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)

确认 JAVA_HOME 实际路径(后续 systemd 配置要用):

readlink -f $(which java)
/usr/lib/jvm/java-17-openjdk-amd64/bin/java

即 JAVA_HOME 为 /usr/lib/jvm/java-17-openjdk-amd64。

💡 启动脚本对 Java 版本做硬校验:低于 17 直接退出并提示 Too old Java version xxx, at least Java 17 is required。

4.2 下载发行包并校验 sha256

cd /opt
wget --tries=3 --timeout=60 -O bifromq-3.3.5-standalone.tar.gz \
  https://github.com/apache/bifromq/releases/download/v3.3.5/bifromq-3.3.5-standalone.tar.gz

下载完成校验:

sha256sum /opt/bifromq-3.3.5-standalone.tar.gz
dd739c43b441dd5008f81543911bea5ec3b3662fdb52d3a9fbd187e902ca76b9  /opt/bifromq-3.3.5-standalone.tar.gz

4.3 解压部署

mkdir -p /usr/share/bifromq
tar -zxf /opt/bifromq-3.3.5-standalone.tar.gz --strip-components 1 -C /usr/share/bifromq/
ls /usr/share/bifromq/
bin
conf
lib
plugins
ls /usr/share/bifromq/bin /usr/share/bifromq/conf
/usr/share/bifromq/bin:
bifromq-start.sh
bifromq-stop.sh
standalone.sh

/usr/share/bifromq/conf:
logback.xml
standalone.yml
目录/文件说明
bin/standalone.sh单机版主控脚本,用法 {start|stop|restart} [-fg]
bin/bifromq-start.sh实际拉起 JVM 的脚本(堆推导、GC 参数、nohup)
bin/bifromq-stop.sh按 StandaloneStarter 进程名找 PID 并停止
conf/standalone.yml主配置文件(YAML,覆盖默认值)
conf/logback.xml日志配置
lib/全部依赖 jar
plugins/插件目录,自带 demo-plugin-3.3.5.jar(含 Prometheus 9090 导出器、事件日志、演示鉴权提供器)
data/、logs/首次启动自动创建

4.4 首次启动

cd /usr/share/bifromq
./bin/standalone.sh start

回显:

Using Java Version 17.0.20.1 locating at 'java'
Total Memory: 31 GB

com.baidu.bifromq.starter.StandaloneStarter process started: 4256

💡 堆推导规则(bifromq-start.sh 实读):默认取总内存的 70% 作为 -Xmx,再取其一半作为 -Xms;MaxDirectMemorySize 取总内存 20%;GC 默认 ZGC。31GB 内存的机器实测默认参数为 -Xms11217m -Xmx22435m。可用 JVM_HEAP_OPTS 或 MEM_LIMIT 环境变量覆盖(见 4.7 节)。

检查端口监听:

netstat -lntp | grep -E "1883|8080|8091|9090"
tcp6   0   0 :::9090          :::*   LISTEN   4256/java
tcp6   0   0 172.17.0.3:8091  :::*   LISTEN   4256/java
tcp6   0   0 :::8080          :::*   LISTEN   4256/java
tcp6   0   0 :::1883          :::*   LISTEN   4256/java
端口用途默认状态
1883MQTT over TCP开启
8080MQTT over WebSocket(路径 /mqtt)开启
8091HTTP 管理 API(REST)开启;默认绑定在 site-local 地址上(本例 172.17.0.3),用 127.0.0.1:8091 访问不通,需用本机实际网卡地址
9090Prometheus 指标(DemoPlugin 提供)开启
1884 / 8443MQTT over TLS / WSS默认关闭
8090HTTPS 管理 API默认关闭

⚠️ 首次启动约需 30~60 秒完成内部存储(inbox store / retain store / dist worker)引导,期间端口可能尚未全部就绪,属正常现象。

4.5 MQTT 连通与基础收发验证

安装 mosquitto 客户端后做完整闭环(先开订阅,再发布):

# 终端 1:后台订阅 native/# 通配主题
(timeout 12 mosquitto_sub -h 127.0.0.1 -p 1883 -t "native/#" -v > /tmp/native.txt 2>&1 &)

# 终端 2:分别以 QoS1、QoS0 发布,并以 QoS1 发一条保留消息
mosquitto_pub -h 127.0.0.1 -p 1883 -t native/q1 -m "native-qos1-ok" -q 1
mosquitto_pub -h 127.0.0.1 -p 1883 -t native/q0 -m "native-qos0-ok" -q 0
mosquitto_pub -h 127.0.0.1 -p 1883 -t native/ret -m "native-retained" -q 1 -r

# 回看订阅端
cat /tmp/native.txt

订阅端实际收到(三条全部通过):

native/q1 native-qos1-ok
native/q0 native-qos0-ok
native/ret native-retained

保留消息语义验证(新建订阅者应立即收到该主题最后一条保留消息):

mosquitto_sub -h 127.0.0.1 -p 1883 -t "native/ret" -C 1 -W 4
native-retained

QoS1 发布确认(-d 调试模式):

mosquitto_pub -h 127.0.0.1 -p 1883 -t native/q1 -m "ack-test" -q 1 -d
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q1, r0, m1, 'native/q1', ... (8 bytes))
Client (null) received PUBACK (Mid: 1, RC:0)
Client (null) sending DISCONNECT

4.6 REST API 验证

BifroMQ 内置 HTTP 管理 API(默认 8091,绑定本机 site-local 地址)。注意:3.3.x 的接口参数通过 HTTP Header 传递,不是 JSON body,报文体即消息 payload:

curl -X POST http://172.17.0.3:8091/pub \
  -H "req_id: 710000031" -H "tenant_id: bifromq" -H "topic: rest/verify" \
  -H "qos: 0" -H "client_type: curl" -H "client_meta_lang: zh" \
  --data-binary "rest-pub-works"

回显:

NO_MATCH

NO_MATCH 且 HTTP 200 表示发布成功、当前无匹配订阅者,属正常返回。会话查询接口(不依赖 dist 子系统,适合做存活探测):

curl -s -o /dev/null -w "%{http_code}\n" -X GET "http://172.17.0.3:8091/session" \
  -H "tenant_id: bifromq" -H "user_id: u1" -H "client_id: not-exist"
404

对不存在的会话返回 404 即为正常。全部接口:POST /pub、POST /retain、GET/DELETE /session、DELETE /kill、PUT /sub、DELETE /unsub。

4.7 JVM 堆调至 256-512MB 并用 jps 实测

cd /usr/share/bifromq
./bin/standalone.sh stop
JVM_HEAP_OPTS="-Xms256m -Xmx512m" ./bin/standalone.sh start

用 jps -v 实测进程参数:

jps -v | grep StandaloneStarter | grep -oE "\-Xms[0-9]+m \-Xmx[0-9]+m"
-Xms256m -Xmx512m

小堆下四端口(1883/8080/8091/9090)全部正常监听,MQTT 收发与 REST 接口复测通过。

另一种方式:设置 MEM_LIMIT(字节),脚本按「70% 上限、一半下限」自动推导。例如 MEM_LIMIT=536870912(512MB)时实测推导出 -Xms179m -Xmx358m。

4.8 配置 systemd 开机自启

创建 /etc/systemd/system/bifromq.service:

[Unit]
Description=Apache BifroMQ Standalone MQTT Broker
After=network.target

[Service]
Type=forking
User=root
Environment=JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
Environment="JVM_HEAP_OPTS=-Xms256m -Xmx512m"
ExecStart=/usr/share/bifromq/bin/standalone.sh start
ExecStop=/usr/share/bifromq/bin/standalone.sh stop
Restart=on-failure
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now bifromq
systemctl is-active bifromq
jps -v | grep StandaloneStarter | grep -oE "\-Xms256m \-Xmx512m"
active
-Xms256m -Xmx512m

⚠️ 实测坑:Environment=JVM_HEAP_OPTS=-Xms256m -Xmx512m(不加引号)会被 systemd 按空格拆成两个变量,jps -v 里只剩 -Xms256m(-Xmx 丢失回落 JVM 默认值 1/4 物理内存)。值里有空格必须用双引号包住整段。

五、日志文件布局

/usr/share/bifromq/logs/
├── stdout.log          # nohup 输出(启动早期日志)
├── info.log            # 主日志:启动序列、Setting 全量 dump、整合配置 dump
├── warn.log / error.log
├── debug.log / trace.log
├── event.log           # 事件采集(demo 插件)
├── plugin.log          # 插件管理器
├── gc-<date>.log       # ZGC 日志(filecount=5, 50m each)
└── basekv/             # 内置存储各组件的 balancer/data/wal 日志

启动成功标志(info.log):

Inbox store started
Retain store started
Dist worker started
MQTT broker started
API server started
Loaded plugin: bifromq-demo-plugin@3.3.5

六、常见问题

6.1 MQTT 订阅被拒(SUBACK 128 / v3.1.1 返回 0x80),发布 QoS1 偶发收不到 PUBACK

根因(本文实测踩中):/tmp 挂载了 noexec。BifroMQ 启动时把 netty 原生 epoll 库解压到 /tmp 加载执行,stdout.log 中会有如下告警:

i.n.util.internal.NativeLibraryLoader  /tmp/libnetty_transport_native_epoll_x86_64...so exists but
cannot be executed even when execute permissions set; check volume for "noexec" flag

此时 CONNECT、QoS0 发布、REST 查询看起来都正常,唯独订阅路径(内部 dist 子系统)报 BatcherUnavailableException: Batcher not found(debug.log 可见),导致 SUBACK 128。

修复:让 /tmp 可执行后重启服务:

mount -o remount,exec /tmp
systemctl restart bifromq

修复后重测,订阅立即返回 0、QoS1 稳定收到 PUBACK。

6.2 访问 8091 管理接口 Connection refused

8091 默认绑定 site-local 地址(本机内网 IP)而非 127.0.0.1。先 ip addr 拿到本机地址再访问;或在 standalone.yml 的 apiServerConfig.host 显式指定 0.0.0.0 后重启。

6.3 启动报 Too old Java version

启动脚本硬校验 Java 主版本 ≥ 17。确认 JAVA_HOME 指向 JDK 17+,或 java -version 输出为 17.x。

6.4 默认堆过大/过小

默认堆 = 物理内存 × 70%,31GB 内存机器会吃 22GB。小规格服务器用 JVM_HEAP_OPTS="-Xms256m -Xmx512m" 显式指定(推荐,见 4.7 节),或用 MEM_LIMIT=536870912 让脚本按 512MB 自动推导(实测得 -Xms179m -Xmx358m)。

6.5 systemd 启动后堆参数不对

见 4.8 节:Environment= 的值含空格必须加双引号,否则空格后内容会被当成独立变量名丢弃。

6.6 连接被拒/鉴权失败

自带 demo 插件的演示鉴权提供器未配置 webhook 时会拒绝部分权限检查。生产环境应在 standalone.yml 配置 authProviderFQN 指向自己的鉴权插件,或为 demo 插件通过 -Dplugin.authprovider.url=http://<webhook>/ 提供 webhook 服务。

七、参考链接