vertx-mqtt icon indicating copy to clipboard operation
vertx-mqtt copied to clipboard

JAVA: keep alive not working

Open konradmichael opened this issue 6 years ago • 4 comments

The keep alive does not seem to work, maybe i also found out why it is so.

Reproduce:

  1. Connect to any remote mqtt-broker (not on your pc).
  2. 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

konradmichael avatar Jan 15 '19 08:01 konradmichael

Pull request for working solution: https://github.com/vert-x3/vertx-mqtt/pull/118

konradmichael avatar Jan 16 '19 08:01 konradmichael

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.

vietj avatar Jan 17 '19 07:01 vietj

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.

konradmichael avatar Jan 17 '19 08:01 konradmichael

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.

konradmichael avatar Jan 17 '19 08:01 konradmichael