Skip to content

常见安装部署问题解答

推荐在哪些操作系统上部署 EMQX?

EMQX 支持在多种操作系统和硬件平台上运行,考虑到企业级部署的稳定性和可靠性,一般来说,我们推荐在 CentOS、Ubuntu、Debian 等 Linux 发行版上部署。

EMQX 支持 Windows 操作系统吗?

不支持。Windows 下建议使用 Docker 来部署 EMQX。

EMQX 推荐的部署方案是什么?

我们推荐以集群方式部署 EMQX,并在集群前端部署负载均衡(Nginx、HAProxy 等)使连接均衡地落到集群的每个节点上。

对于通信安全有较高要求的用户,我们建议为客户端启用 TLS 连接,并在 LB 侧终结 TLS 连接,即客户端与 LB 之间采用 TLS 加密通信,LB 与 EMQX 节点之间则仍然采用 TCP 通信。

由于 EMQX 节点并不对公网暴露端口,因此并不会降低整体的安全性,但通过 TLS 卸载,可以有效节省 EMQX 的资源消耗。

我的设备数量并不多,消息吞吐也不高,还需要部署集群吗?

即使设备数量不多、消息吞吐也不高,在生产环境下部署集群仍然是很有意义的。集群能提高系统的可用性,降低单点故障的可能性。即便有节点宕机,集群内其他健康节点也可以继续提供服务,保证业务不受影响。

部署 EMQX 开源版 Core + Repl 集群失败

从 EMQX v5.8 开始,仅 EMQX 企业版支持 Core + Replicant 节点集群,因此在使用 EMQX Operator 部署 EMQX 开源版 Core + Repl 集群时,可能会遇到 EMQX 自定义资源一直处于 replicantNodesProgressing 状态,且 EMQX Repl Pod 反复崩溃(Crash)的情况。

建议部署纯 Core 节点的开源版集群,或者部署 Core + Repl 的企业版集群。

EMQX 启动失败时该如何排查?

EMQX 启动失败时,可以查看 日志目录 下的 emqx.log.Nerlang.log.N 获取详细的错误提示。或者执行 emqx console 从控制台启动 EMQX,这样错误日志将直接输出到控制台。然后根据提日志内容,在本页面中查找对应的解决办法,或在我们的 askemq 论坛发帖寻求支持。

EMQX 启动失败,日志提示 “logger: command not found”

安装以下依赖即可:

  • CentOS/Redhat

    $ yum install rsyslog
  • Ubuntu/Debian

    $ apt-get install bsdutils

EMQX 启动失败,日志提示 “...{on_load_function_failed,crypto}...”

该日志表示 EMQX 依赖的 Erlang/OTP 中的 crypto 应用启动失败,这通常是当前系统安装的 OpenSSL 版本与 EMQX 依赖的 OpenSSL 版本不同,或者当前系统并未安装 OpenSSL 导致的。

重要提示

以下解决方案仅供参考示例。

所列源版本是根据当前已知信息选择的,但可能已过时或存在漏洞。

建议直接从操作系统的包管理器中安装 libcrypto 以获取最新的安全更新。

进入到 EMQX 的安装目录(如果使用包管理工具安装 EMQX,则应该进入与 EMQX 的 lib 目录同级的位置):

bash
## 安装包安装
$ cd emqx

## 包管理器安装,例如 yum。则它的 lib 目录应该在 /lib/emqx
$ cd /lib/emqx

查询 crypto 依赖的 .so 动态库列表及其在内存中的地址:

bash
$ ldd lib/crypto-*/priv/lib/crypto.so

lib/crypto-4.6/priv/lib/crypto.so: /lib64/libcrypto.so.10: version `OPENSSL_1.1.1' not found (required by lib/crypto-4.6/priv/lib/crypto.so)
        linux-vdso.so.1 =>  (0x00007fff67bfc000)
        libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007fee749ca000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fee74609000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fee74404000)
        libz.so.1 => /lib64/libz.so.1 (0x00007fee741ee000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fee74fe5000)

其中 OPENSSL_1.1.1' not found 表明相应版本的 OpenSSL .so 库未正确安装。

源码编译安装 OPENSSL 1.1.1,并将其 .so 文件放置到可以被系统识别的路径:

bash
## 下载最新版本 1.1.1
$ wget https://www.openssl.org/source/openssl-1.1.1c.tar.gz

## 上传至 ct-test-ha
$ scp openssl-1.1.1c.tar.gz ct-test-ha:~/

## 解压并编译安装
$ tar zxf openssl-1.1.1c.tar.gz
$ cd openssl-1.1.1c
$ ./config
$ make test  # 执行测试;如果输出 PASS 则继续
$ make install

## 确保库的引用
$ ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/libssl.so.1.1
$ ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1

完成后,在 EMQX 的 lib 同级目录下执行 ldd lib/crypto-*/priv/lib/crypto.so ,检查是否已能正确识别。如果不再有 not found.so 库,即可正常启动 EMQX。

EMQX 启动失败,日志提示 “libatomic.so.1: cannot open shared object file: No such file or directory”

这个错误的原因是当前系统缺少了 libatomic 这个依赖项,解决办法是安装这个依赖项:

# Rocky Linux, CentOS, ...
yum install -y libatomic
# Debian, Ubuntu, ...
apt install -y libatomic

如果你手动安装 RPM 或 DEB 包,可能会在安装时就遇到以下提示:

$ rpm -ivh emqx-5.7.0-el8-amd64.rpm
error: Failed dependencies:
libatomic is needed by emqx-5.7.0-el8-amd64.rpm

解决办法仍然是先手动安装 libatomic 这个依赖项。

当然,我们最推荐的安装方式是使用包管理器(yum、apt 等)安装,它们会自动安装所需依赖,不用我们额外操心。

使用 Docker 启动 EMQX 失败,日志提示 “Permission denied”

当你打算以目录挂载的方式持久化 EMQX 数据时:

sudo docker run -d --name emqx -p 18083:18083 -p 1883:1883 -v /emqx/data:/opt/emqx/data -v /emqx/log:/opt/emqx/log emqx:latest

你可能会遇到容器启动失败,并提示以下错误:

mkdir: cannot create directory '/opt/emqx/data/configs': Permission denied

这是因为 EMQX 在容器中以 Linux 用户 emqx 运行,而你宿主机中的目录却可能是在 root 用户下创建的,因此 EMQX 自然无法在这些目录下创建目录或文件。

想要解决这个问题,你可以在宿主机中创建一个 emqx 用户,然后由该用户来创建需要挂载的目录,或者直接将已经创建好的 data、log 目录的权限修改为 777。

当然,最推荐的方式还是以命名数据卷的方式实现 EMQX 数据持久化,这样就不必再关心权限问题:

sudo docker volume create --name emqx-data
sudo docker volume create --name emqx-log
sudo docker run -d --name emqx -p 18083:18083 -p 1883:1883 -v emqx-data:/opt/emqx/data -v emqx-log:/opt/emqx/log emqx:latest

EMQX 启动时日志提示端口被占用(eaddrinuse)应该怎么办?

默认情况下,EMQX 启动时会占用 7 个端口,它们分别是:

  1. 1883,用于 MQTT over TCP 监听器,可通过配置修改。
  2. 8883,用于 MQTT over SSL/TLS 监听器,可通过配置修改。
  3. 8083,用于 MQTT over WebSocket 监听器,可通过配置修改。
  4. 8084,用于 MQTT over WSS (WebSocket over SSL) 监听器,可通过配置修改。
  5. 18083,HTTP API 服务的默认监听端口,Dashboard 功能也依赖于这个端口,可通过配置修改。
  6. 4370,用于 EMQX 分布式集群远程函数调用、Mnesia 数据同步等。即便没有组成集群,这个端口也会被默认占用。这个监听端口实际上应该是 BasePort (4370) + Offset,4370 固定无法修改,Offset 则由节点名称(Name@Host)中 Name 部分的数字后缀决定,没有数字后缀则默认为 0。例如 emqx@127.0.0.1 的 Offset 为 0,emqx1@127.0.0.1 的 Offset 为 1。
  7. 5370,用于分担上一端口压力的集群 RPC 端口,主要用于节点间转发 MQTT 消息。与 4370 端口类似,即便没有组成集群,这个端口也会被默认占用,并且它实际上应该是 BasePort (5370) + Offset,5370 固定无法修改,Offset 则由节点名称(Name@Host)中 Name 部分的数字后缀决定,没有数字后缀则默认为 0。

完整的 WARNING 日志如下:

WARNING: Default (insecure) Erlang cookie is in use.
WARNING: Configure node.cookie in /usr/lib/emqx/etc/emqx.conf or override from environment variable EMQX_NODE__COOKIE
WARNING: NOTE: Use the same cookie for all nodes in the cluster.

只有使用相同 Cookie 的 EMQX 节点才能组成一个集群。虽然 Cookie 并不能保证集群的通信安全,但它可以避免节点连接到它不打算与之通信的集群。EMQX 节点默认统一将 emqxsecretcookie 作为 Cookie,所以我们会推荐用户在搭建集群时更改 Cookie 的值。

第二条 WARNING 日志则提示了修改 Cookie 的两种方式,分别为 emqx.conf 配置文件中的 node.cookie,和环境变量 EMQX_NODE__COOKIE

使用 Docker 部署 EMQX 时,为什么容器重启会丢失已经配置的规则、资源等数据?

EMQX 的运行时数据,譬如规则和资源的配置、保留消息等等,它们都存储在 /opt/emqx/data 目录下,所以为了保证这部分数据不会因容器重启而丢失,我们需要将 /opt/emqx/data 目录挂载到本地主机目录或者数据卷中去。

但我们可能会发现,即便已经挂载了 /opt/emqx/data 目录,数据仍然可能会在容器重启后丢失。这是因为 EMQX 的运行时数据实际上存储在 /opt/emqx/data/mnesia/${Node Name} 目录。所以数据丢失,实际上是容器重启后 EMQX 的节点名发生了变化,进而导致 EMQX 创建了一个全新的存储目录。

EMQX 节点名由 Name 和 Host 两部分组成,其中 Host 默认来自容器的 IP 地址。在默认的网络配置下容器一旦重启它的 IP 就可能发生变化,所以我们要做的就是让容器的 IP 保持固定。

EMQX 提供了一个环境变量 EMQX_HOST,允许我们自行设置节点名的 Host 部分。当然前提是这个 Host 必须是其他节点可以连接的,所以我们还需要配合网络别名使用:

docker run -d --name emqx -p 18083:18083 -p 1883:1883 -e EMQX_HOST=alias-for-emqx --network example --network-alias alias-for-emqx --mount type=bind,source=/tmp/emqx,target=/opt/emqx/data emqx:5.8.3

为什么使用 docker-compose 正常启动容器,且打开 Dashboard 管理界面也正常,但是显示 unhealthy 状态?

bash
docker-compose ps
NAME      IMAGE                         COMMAND                  SERVICE   CREATED          STATUS                    PORTS
emqx1     emqx/emqx:latest   "/usr/bin/docker-ent…"   emqx     120 seconds ago   Up 110 seconds (unhealthy)   0.0.0.0:1883->1883/tcp, :::1883->1883/tcp, 0.0.0.0:18083->18083/tcp, :::18083->18083/tcp

EMQX 的健康检查依赖于 ./bin/emqx_ctl status 命令,如果这个命令执行失败,则容器会显示为 unhealthy 状态。

yaml
healthcheck:
      test: ["CMD", "/opt/emqx/bin/emqx_ctl", "status"]
      interval: 60s
      timeout: 15s
      retries: 3

手动执行 ./bin/emqx_ctl status 命令:

emqx@docker:/opt/emqx$ emqx_ctl status
Node emqx@docker not responding to pings.

表明命令连不上节点,这是由于启动容器时 network 没有使用 alias,且不是 FQDN 格式,无法找到节点。

解决办法:

  1. 修改 Docker 的 hostname 和 emqx 的节点名一致。
  2. 修改 docker-compose.yml 文件,添加 hostname 配置。
yaml
# xxx.yyy.zzz(docker.emqx.com) 符合 FQDN 格式。
hostname: docker.emqx.com
 environment:
      - EMQX_HOST=docker.emqx.com

由于 EMQX 使用 data/mnesia/<节点名> 作为数据存储目录,使用 hostname 或者 FQDN 等固定的信息作为节点名(不推荐使用 IP),还可以避免因为节点名称变动导致数据丢失。

推荐使用 EMQX Docker Compose 一键生成器 一键生成生产就绪的 docker-compose.yml 文件。