emqx MQTT 代理在重启后不保持会话

问题描述

我正在使用 emqx 代理,我想在磁盘上保留会话,以便在代理因任何原因重新启动时我可以恢复会话。

我做什么:

  • 使用 docker-compose 启动 emqx 代理:
emqx1:
    image: emqx/emqx:v4.0.0
    environment:
      - EMQX_NAME=emqx
      - EMQX_NODE__NAME=emqx.local.node
      - EMQX_HOST=node1.emqx.io
      - EMQX_CLUSTER__disCOVERY=static
      - EMQX_RETAINER__STORAGE_TYPE=disc
    volumes:
      - emqx-data:/opt/emqx/data
      - emqx-etc:/opt/emqx/etc
      - emqx-log:/opt/emqx/log
    ports:
      - 18083:18083
      - 1883:1883
      - 8081:8081
    networks:
      gateway-api:
        aliases:
        - node1.emqx.io
  • 使用以下配置启动带有 Paho MQTT 库的 Go 订阅客户端。客户端的代码可以在paho repo
  • 的“stdinpub”和“stdoutsub”文件夹中找到
clientId = "sub1"
qos = 1
clean = false
topic_subscribe = "topic1"
  • 使用此配置启动 Go 发布客户端并发布消息:
clientId = ""
clean = true

和消息:

qos = 1
retain = false
topic = "topic1"
payload = "test"
  • 然后我断开客户端“sub1”的连接并使用 qos=1 发送第二条消息:
qos = 1
retain = false
topic = "topic1"
payload = "test2"

此消息未传递给客户端“sub1”,因此代理将其排队(qos=1)。事实上,如果我重新启动 sub1 客户端,它确实会收到消息“test2”。
但是如果我在重新启动客户端“sub1”之前重新启动代理,那么“test2”就会丢失并且不会被传送。

我尝试了相同的测试,将 retain 设置为 true,即使在代理重新启动后,消息“test2”也能很好地传递。因此,broker 将保留的消息很好地保存在磁盘上,而不是客户端会话。

知道为什么吗?是否有我应该更改的配置以在磁盘上保留客户端会话?

解决方法

正如评论中所说。

客户端会话存储功能仅在“企业”付费版 emqx 中可用,而不是免费使用版。

这可以从 Feature list 以及问题 12 也询问该功能看出。

,

retainer 消息存储在磁盘中:

# etc/plugins/emqx_retainer.conf

## Where to store the retained messages.
retainer.storage_type = disc_only

EMQ X 开源产品不支持消息在服务器内的持久化,这是一种架构设计选择。首先,EMQ X 解决的核心问题是连接和路由;其次,我们认为内置持久化是错误的设计。

具有内置消息持久性的传统 MQ 服务器,例如广泛使用的 JMS 服务器 ActiveMQ,几乎在每个主要版本中都重新设计了持久性部分。内置消息持久化的设计存在两个问题:

如何平衡内存和磁盘的使用?消息路由是基于内存的,而消息存储是基于磁盘的。 多服务器分布式集群架构下,如何放置Queue,如何复制Queue的消息? Kafka针对以上问题做了正确的设计:完全基于磁盘分布式Commit Log的消息服务器。

EMQ X 在设计上将消息路由和消息存储职责分离后,数据复制、容灾备份甚至应用集成都可以在数据层面灵活实现。

在 EMQ X 企业版产品中,您可以通过规则引擎或插件将消息持久化到 Redis、MongoDB、Cassandra、MySQL、PostgreSQL 等数据库和 RabbitMQ、Kafka 等消息队列中。