微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何有效地为 MQTT 设置连接超时?

如何解决如何有效地为 MQTT 设置连接超时?

我想确保我的程序在无法连接到 MQTT 服务器时崩溃。为此,我将 ConnectTimeout 设置为 10 秒,但是当连接到不存在的服务器(名称不存在)时,对 MQTT 的调用挂起

package main

import (
    "fmt"
    "time"

    mqtt "github.com/eclipse/paho.mqtt.golang"
)

func main() {
    timeout,_ := time.ParseDuration("10s");
    opts := mqtt.NewClientOptions()
    opts.Addbroker("tcp://this.does.not.resolve.example.coooom:1883")
    opts.SetClientID("monitor")
    opts.SetorderMatters(false)
    opts.SetConnectRetry(true)
    opts.SetConnectTimeout(timeout)
    client := mqtt.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(fmt.Sprintf("cannot connect to MQTT: %v",token.Error()))
    }
}

如何正确设置超时时间?

解决方法

opts.SetConnectRetry(true) 似乎将连接置于循环中(没有任何错误消息)。通过将代码更改为 ...

package main

import (
    "fmt"
    "time"

    mqtt "github.com/eclipse/paho.mqtt.golang"
)

func main() {
    timeout,_ := time.ParseDuration("10s");
    opts := mqtt.NewClientOptions()
    opts.AddBroker("tcp://this.does.not.resolve.example.coooom:1883")
    opts.SetClientID("monitor")
    opts.SetOrderMatters(false)
    opts.SetConnectTimeout(timeout)
    client := mqtt.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(fmt.Sprintf("cannot connect to MQTT: %v",token.Error()))
    }
    opts.SetConnectRetry(true)
}

...连接正确失败(并且希望,如果连接断开,客户端仍会重新连接)

编辑:我认为在连接尝试后移动 opts.SetConnectRetry(true) 不会使其自动重新连接(因为选项已经被使用)。这是一个 catch-22 的情况。

,

来自docs for SetConnectRetry

SetConnectRetry 设置连接函数是否会在失败时自动重试连接(当为真时,连接函数返回的令牌将不会完成,直到连接建立或被取消)如果 ConnectRetry 为真,则订阅应该在 OnConnect 处理程序中请求 将此设置为 TRUE 允许在建立连接之前发布消息。

所以当 SetConnectRetry(true) Connect() 将重试直到成功或您停止它。不会尝试确定错误是否是永久性的,因为这非常困难(例如,无法解决 this.does.not.resolve.example.coooom 可能是由于互联网连接中断)。

注意:有一个单独的选项 SetAutoReconnect 控制断开的连接(在初始连接成功建立后)是否会导致客户端自动重新建立连接。

值得注意的是,添加 ConnectRetry 选项的主要原因是允许用户在连接出现之前发布消息(它们会在连接建立时自动发送)。这个想法是您应该能够调用 Connect 然后使用库而不必担心网络状态(显然,如果网络关闭,您将不会收到消息!)。

就如何与 SetConnectRetry 交互而言,SetConnectTimeout docs 可能不那么清楚:

SetConnectTimeout 限制客户端在超时前尝试打开与 MQTT 服务器的连接时将等待的时间。持续时间 0 永远不会超时。默认 30 秒。目前仅适用于 TCP/TLS 连接。

所以这控制了我们等待单个连接尝试完成的时间。当 SetConnectRetry (true) 时,每次尝试连接时都会使用此间隔(每次尝试重新开始)。没有 RetryConnectionsFor 类型设置。

来自自我回答:

...连接正确失败(并且希望,如果连接断开,客户端仍会重新连接)

一旦调用了 NewClient(o *ClientOptions),您就无法更改选项(NewClient 获取选项的副本)。这样做是因为在操作正在进行时更改选项会导致不可预测的结果(例如,如果您在调用 opts.SetConnectRetry(true) 之后调用 Connect,那么结果将取决于 Connect 调用是否已完成与否,这是不可预测的)。

我不太确定您所说的“确保我的程序在无法连接到 MQTT 服务器时崩溃”是什么意思,但我使用的方法类似于以下内容(将适当的操作替换为 {{1} } 语句) - 请注意,我还没有编译/测试这个:

fmt.PrintLn

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。