【问题标题】:Mosquitto subscriber receiving extra messageMosquitto 订阅者收到额外消息
【发布时间】:2020-10-12 22:26:59
【问题描述】:

我正在探索 mosquitto 作为一个完整的初学者。我有一个 golang 测试程序,我正在使用它来查看它如何管理消息,但该程序的后续运行显示收到了额外的消息。

import (
    mqtt "github.com/eclipse/paho.mqtt.golang"
    log "github.com/sirupsen/logrus"
    "strconv"
    "time"
)
var sent int
var received int

func Test() {
    sent  = 0
    received = 0
    const TOPIC = "mytopic/test"

    opts := mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("client1").SetResumeSubs(false).SetAutoReconnect(false).SetCleanSession(true)

    client1 := mqtt.NewClient(opts)
    if token := client1.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }
    if token := client1.Subscribe(TOPIC, 2, receiver1); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }

    defer howManySent()
    defer howManyReceived()
    defer client1.Disconnect(1)

    for index:=0;index<3;index++ {
        sendMsg := "client1 message " + strconv.Itoa(index)
        if token := client1.Publish(TOPIC, 2, true, sendMsg); token.Wait() && token.Error() != nil {
            panic(token.Error())
        } else {
            sent++
        }
        time.Sleep(1 * time.Second)
    }
    time.Sleep(1*time.Second)
}

func howManyReceived() {
    log.Warn("RECEIVED:", received)
}

func howManySent() {
    log.Warn("SENT:", sent)
}

func receiver1(client mqtt.Client, msg mqtt.Message) {
    received++
    msg.Ack()
    output := "message id:" + strconv.Itoa(int(msg.MessageID())) + " message = " + string(msg.Payload())
    log.Warn(output)
}

第一次运行的输出:

WARN[0000] message id:1 message = client1 message 0     
WARN[0001] message id:2 message = client1 message 1     
WARN[0002] message id:3 message = client1 message 2     
WARN[0004] RECEIVED:3                                   
WARN[0004] SENT:3      

第二次运行的输出:

WARN[0000] message id:4 message = client1 message 2     
WARN[0000] message id:5 message = client1 message 0     
WARN[0001] message id:6 message = client1 message 1     
WARN[0002] message id:7 message = client1 message 2     
WARN[0004] RECEIVED:4                                   
WARN[0004] SENT:3    

我的配置文件是mosquitto默认安装的,只是我关闭了持久化看看有没有帮助:

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /var/run/mosquitto.pid

persistence false
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

我做错了什么?

【问题讨论】:

    标签: go mqtt mosquitto


    【解决方案1】:

    Publish定义如下:

    Publish(topic string, qos byte, retained bool, payload interface{}) Token
    

    因此,当您调用 token := client1.Publish(TOPIC, 2, true, sendMsg) 时,您正在发布一条将 retained 设置为 true 的消息。 Retain 是与消息一起传递给代理的标志,表示:

    如果 RETAIN 标志设置为 1,在客户端发送给服务器的 PUBLISH 数据包中,服务器必须存储应用消息及其 QoS,以便可以将其传递给订阅匹配其主题名称的未来订阅者[MQTT-3.3.1-5]。建立新订阅后,必须将每个匹配主题名称上的最后保留消息(如果有)发送给订阅者 [MQTT-3.3.1-6]。

    带有retain 集的每条新消息都会替换任何以前的消息,因此当您的第一次执行完成时,消息2 会被保留。这会在客户端重新连接时发送给客户端(意味着您看到的结果是预期的)。如果您将呼叫更改为 token := client1.Publish(TOPIC, 2, false, sendMsg),它将按您的预期运行。

    mosquitto docs 对persistence 标志说以下内容:

    如果为 true,则连接、订阅和消息数据将写入 mosquitto.db 中由 persistence_location 指定的位置的磁盘。当 mosquitto 重启时,它会重新加载 mosquitto.db 中存储的信息

    所以这只有在你重启 Mosquitto 时才会产生影响;即使此标志设置为false,会话信息仍将存储在内存中。

    【讨论】:

    • 但是消息已发送并确认。为什么会被存储?鉴于我已将持久性配置为 false 并已验证不存在 mosquitto.db 文件......更奇怪的是,它存储在哪里? :D
    • 我猜它存储在内存中?但我尝试重新启动服务器并得到相同的结果。另外,如果我使用相同的客户端 ID,这是否会被视为新订阅?
    • 它存储在内存中。如果您在mosquitto.conf 中有persistence false,那么在重新启动 Mosquitto 后第一次运行您的应用程序时,您不应该收到额外的消息。参考same client ID;您正在使用SetCleanSession(true),它告诉代理在断开连接时丢弃客户端会话。无论如何,MQTT-3.8.4-3 规定即使已经有相同的订阅,也要发送保留的消息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 1970-01-01
    相关资源
    最近更新 更多