'How to set Microsoft.Azure.Devices.Client.DeviceClient KeepAliveInSeconds to a higher number than 30

I am investigating using MQTT (or AMQP) over a satellite connection. I am using MQTT over HTTPS towards an IoT Hub in Azure. Data is very expensive on satellite and I am trying to minimize the "idle" consumption of this connection. I can do this by changing how often the SaS token is renewed (default 1 hour) and the Keep Alive.

I am using the DeviceClient from the Microsoft.Azure.Devices NuGet package and there I can create a TransportSettings object and set the keep alive:

ITransportSettings transportSettings = new MqttTransportSettings(TransportType.Mqtt_WebSocket_Only)
{
    KeepAliveInSeconds = 90,
};

I then create the connection like this:

var client = DeviceClient.CreateFromConnectionString(connectionString , new[] { transportSettings });

What I experience is. If I omit the transport settings, the connections sends a keep alive every 5 seconds. If I set the keep alive to anything from 30 and above, it always sends the keep alive every 30 seconds. The description of the KeepAliveInSeconds property tells the default is 300 seconds: KeepAliveInSeconds property description

But my Wireshark trace tells a different story: Wireshark trace

When no MqttTransportSettings are given in the CreateFromConnectionString then it sends a keep alive every 5 seconds. When i add the settings, I can set the keep alive to 10 or 30 seocnds and this works, but if I set it to 90 like this example, it stays on the 30 seconds ()or so the Wireshark trace show). I tried to look in Azure if I can change anything there. And there are no settings like this on the IoT Hub.

So hopefully someone else experienced this and found a solution, from the client side to have a keep alive that is not sent every 5 or 30 seconds. My goal is like once ever 2-5 minutes.



Solution 1:[1]

I am one of the devs on this SDK and I took a look at what is causing this.

Our WebSocket implementations use the ClientWebSocket class to create the connection. By default the ClientWebSocket has a KeepAliveInterval of 30 seconds. This KeepAliveInterval controls the WebSocket Ping request. This is different than our own KeepAliveInSeconds which is used for a specific PINGREQ packet in MQTT.

We do not expose a way to set the WebSocket KeepAliveInterval, but I created this issue to track and will discuss this with the team internally.

There is one caveat to setting the KeepAliveInSeconds. When it is used by the SDK it is divided by 4. See this documentation for details.

The client will send a ping request 4 times per keep-alive duration set. It will wait for 30 seconds for the ping response, else mark the connection as disconnected. Setting a very low keep-alive value can cause aggressive reconnects, and might not give the client enough time to establish a connection before disconnecting and reconnecting.

Just incase someone comes across this and is using AMQP and has a similar question. At the time of this answer, the AMQP service has an internal keep alive interval of 4 minutes that it imposes on the client. (This is also independent of the WebSocket KeepAliveInterval.) This interval cannot be changed as it's set at the service.

Solution 2:[2]

The fix for this has been released with version 1.41.0.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 James Davis - MSFT
Solution 2 David R. Williamson