Mqtt Last Will & Testament (LWT) 消息 - LWT 消息的时间问题

问题描述 投票:0回答:2

我有一个

Windows Service
在多个盒子上运行,
publishing messages
HiveMq Mqtt Broker。 到目前为止还不错。

但是,我注意到当我手动停止其中一个 Win 服务时 - 我的浏览器 Mqtt 客户端立即 获取最后一条 Last Will 消息(当然我正在订阅)。

我不应该根据配置的秒数而不是立即接收 LWT 消息吗?它可能与

retained
标志有关吗?

感觉我的LWT配置有问题

这是我的 C# 代码片段(在我的 Win Svc 中)-

public ManagedMqttClientOptions WsSecureClientOptions(PublisherSubscriber pubSubType) {
  // Build LWT message, then Client Options
  MqttModel lastWill = new MqttModel();
  lastWill.message = "BMAZZO box is OFFLINE";
  lastWill.datestamp = DateTime.Now;
  lastWill.status = ConnectionStatus.Offline;
  LastWillMsgJson = JsonConvert.SerializeObject(lastWill, Formatting.Indented);

 
  clientOptionsBldr = new MqttClientOptionsBuilder()
        .WithClientId(".netWinSvc-BMAZZO-Pub")
        .WithProtocolVersion(MqttProtocolVersion.V500)
        .WithWebSocketServer("<broker-url>:8884/mqtt")
        .WithCredentials("myUser", "myPswd")                                            
        .WithCleanSession(true)
        .WithWillQualityOfServiceLevel(2)
        .WithWillTopic('myApp\myLAN\Box\BMAZZO\Status')   // LAST WILL TOPIC
        .WithWillRetain(true)                           // RETAIN
        .WithWillPayload(LastWillMsgJson)               // WILL PAYLOAD
        .WithKeepAlivePeriod(TimeSpan.FromSeconds(30))         // KEEP ALIVE, 30 SECS
        .WithTls(
            new MqttClientOptionsBuilderTlsParameters()
            {
                UseTls = true,
                SslProtocol = System.Security.Authentication.SslProtocols.Tls12,
                Certificates = new List<X509Certificate2>() { x509Cert }
            });
            
    return managedClientOptions;
 }
          
 public async Task Publish(string messageIn, string topic, IManagedMqttClient pubClient = null, ConnectionStatus status = ConnectionStatus.Unknown)
    {            
        MqttModel message = new MqttModel();
        message.message = messageIn;
        message.datestamp = DateTime.Now;
        message.status = status;
        var payload = JsonConvert.SerializeObject(message, Formatting.Indented);

        var send = new MqttApplicationMessageBuilder()
            .WithTopic("myApp\myLAN\Box\BMAZZO\Status")
            .WithPayload(payload)
            .WithMessageExpiryInterval(86400)   // seconds per day
            .WithQualityOfServiceLevel(2)       // QOS
            .WithRetainFlag(true)               // retain = true
            .Build();


                applog.Debug($"Mqtt Publish() to broker - message = {messageIn} / {topic} ");
                await this.managedMqttClientPublisher.EnqueueAsync(send);
                
       await this.managedMqttClientPublisher.EnqueueAsync(send);

    }

示例:我在

2023-04-25 17:30:00
停止了 Win Svc,并立即在我的浏览器中收到一条消息,该服务是
OFFLINE
分钟前的
2023-04-25T17:26:43

 {message: 'Offline BMAZZO 10.2.23.62', status: 1, source: 'BMAZZO', datestamp: '2023-04-25T17:26:43.7074826-04:00'}

另一个例子:我刚刚在

17:58
停止了服务,LWT 消息似乎显示了之前的一条 LWT 消息(保留在代理中?)。

  {message: 'Offline BMAZZO 10.2.23.62', status: 1, source: 'BMAZZO', datestamp: '2023-04-25T17:47:32.4730311-04:00'}

也许

WithWillRetain
标志应该设置为false?

任何想法或建议表示赞赏。

鲍勃

mqtt hivemq mqttnet mqtt.js
2个回答
0
投票

很高兴听到 HiveMQ Broker 的实施故事!

我想澄清的一个细节——当这个服务终止时,是否有任何当前功能在服务终止时发送 DISCONNECT 数据包?当前的功能似乎表明在连接关闭时正在触发正常断开连接。根据所使用的 HiveMQ 代理的版本,实现自定义侦听器以登录 onDisconnect 或 onServerInitiatedDisconnect 原因代码以进行更具体的诊断可能是值得的。有关实施的更多信息可在此处找到:https://docs.hivemq.com/hivemq/4.11/extensions/registries.html#on-server-disconnect.

此外,我鼓励任何对 HiveMQ 有疑问的人访问我们的社区论坛,网址为 https://community.hivemq.com/!

最好的,

HiveMQ 团队的 Aaron


0
投票

首先注意 - 在评论中您引用了 v3 规范(“3.1.2.5 Will Flag specs at docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html”)。您正在使用 MQTT v5 (

.WithProtocolVersion(MqttProtocolVersion.V500)
),这是一个规格差异很大的领域。以下是基于我对规范的理解(因此可能包含错误!)。

您所看到的内容符合 MQTT v5 规范,它说:

服务器延迟发布客户的遗嘱消息,直到遗嘱延迟间隔过去或会话结束,以先发生者为准

所以这里的问题是“session什么时候结束”;我相信规范的相关部分是:

会话可以在一系列网络连接中继续。它的持续时间与最新的网络连接加上会话到期间隔一样长。

您的代码不使用

SessionExpiryInterval()
选项,这意味着会话将在断开连接后立即过期

如果会话到期间隔不存在,则使用值 0。

所以当您的客户断开连接时,会话结束并且遗嘱被发布。

参考保命;这些是使客户端能够检测半开连接的机制。 通常(特别是当一个服务被干净地关闭时)连接的另一端会在连接关闭时收到通知并且保持活动状态无关紧要。

请注意,另一个因素可能正在发挥作用(如@Aaron Franz 所述):

当我手动停止其中一个 Win 服务时

手动停止服务可能会导致完全断开连接(即发送 DISCONNECT 数据包)。干净地断开连接(“正常断开连接”) 删除遗嘱但您也可以选择发送它(这可能会改变会话到期间隔)。

© www.soinside.com 2019 - 2024. All rights reserved.