vertx-mqtt
vertx-mqtt copied to clipboard
JAVA: keep alive not working
The keep alive does not seem to work, maybe i also found out why it is so.
Reproduce:
- Connect to any remote mqtt-broker (not on your pc).
- unplug network cable Result: Nothing. The connection will not be closed
If you replug the network, the connection will be closed and reconnected (in my setup).
Potential error: MqttClientImpl line 140 https://github.com/vert-x3/vertx-mqtt/blob/c8213e0f41150a1a02f4ad1185762494b52c6350/src/main/java/io/vertx/mqtt/impl/MqttClientImpl.java#L140
Context:
public MqttClientImpl(Vertx vertx, MqttClientOptions options) {
// copy given options
NetClientOptions netClientOptions = new NetClientOptions(options);
netClientOptions.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
this.client = vertx.createNetClient(netClientOptions);
this.options = options;
}
The DEFAULT_IDLE_TIMEOUT
is 0. Zero disabled timeout detection,
I belive this should be keepAlive * 1.5
My current workaround is:
Future<Void> disconnectTask;
ScheduledExecutorService scheduledExecutorService;
int keepAlive = 30;
int timeout = 45;
// keep alive with multiplier to prevent multiple pings
mqttClientOptions.setKeepAliveTimeSeconds(keepAlive * 2);
mqttClient.pingResponseHandler(e -> {
// cancel timeout task
disconnectTask.cancel(false);
// schedule new timeout task
disconnectTask = scheduledExecutorService.schedule(() -> {
logger.warn("disconnecting because keep alive fails!");
client.disconnect();
return null;
}, timeout, TimeUnit.SECONDS);
// keep alive will not be send if other messages are processed,
// force sending or it will get complicated!
scheduledExecutorService.schedule(() -> client.ping(), keepAlive, TimeUnit.SECONDS);
}
I would be glad to receive some feedback
Pull request for working solution: https://github.com/vert-x3/vertx-mqtt/pull/118
can you elaborate what does the 1.5 factor does ? it is not clear to me what is the actual issue and what the fix changes.
Issue: Client will not detect a missing ping response as a disconnect. Fix: terminates connection if no response is comming from broker (timeout)
The use of the keepAlive-Message is to detect if the connection to the broker is lost. So if the keepAlive message is no longer responded by the broker, the connection is dead.
Currently you will not be informed if the connection to your mqtt-broker is lost, status will still be "connected". With the above workaround or my pull-request you will disconnect from the broker if the keep-alive is not send.
The Factor 1.5
is comming from the MQTT-(Spec), but from the broker side of it.
The broker must disconnect a client that does not send a a message or a PINGREQ packet in one and a half times the keep alive interval
Source: HiveMQ - keep alive
You can also use a factor of 2 or 3 as the timeout, but I wanted to stay close to the spec.
Update:
The DEFAULT_IDLE_TIMEOUT is 0. Zero disabled timeout detection, I belive this should be keepAlive * 1.5
This is not working, I tried it, see the pull-request for a working solution.