INT-3923: Fix MQTT Reconnect Logic
JIRA: https://jira.spring.io/browse/INT-3923 Fixes: #2046 Previously, when connection is lost, the inbound adapter attempted to reconnect on a schedule with a fixed delay. If a connection was again lost, while the schedule is still running, we can end up with another scheduled task running. This is benign aside from the DEBUG log noise because the scheduled task tests the connection before reconnecting. However, if the `recoveryInterval` is short, it could consume CPU. Change the reconnect to be a one-time scheduled task and reschedule if it fails to reconnect. Synchronize all access to the `connected` field. Add a test case with a short recovery interval, before this fix, we see many logs `Attempting reconnect`.
This commit is contained in:
committed by
Artem Bilan
parent
218daa94e8
commit
d8cbcd1310
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.integration.mqtt.inbound;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.IMqttAsyncClient;
|
||||
@@ -138,6 +139,7 @@ public class MqttPahoMessageDrivenChannelAdapter extends AbstractMqttMessageDriv
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
Assert.state(getTaskScheduler() != null, "A 'taskScheduler' is required");
|
||||
super.doStart();
|
||||
try {
|
||||
connectAndSubscribe();
|
||||
@@ -149,7 +151,7 @@ public class MqttPahoMessageDrivenChannelAdapter extends AbstractMqttMessageDriv
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
protected synchronized void doStop() {
|
||||
cancelReconnect();
|
||||
super.doStop();
|
||||
if (this.client != null) {
|
||||
@@ -219,7 +221,7 @@ public class MqttPahoMessageDrivenChannelAdapter extends AbstractMqttMessageDriv
|
||||
}
|
||||
}
|
||||
|
||||
private void connectAndSubscribe() throws MqttException {
|
||||
private synchronized void connectAndSubscribe() throws MqttException {
|
||||
MqttConnectOptions connectionOptions = this.clientFactory.getConnectionOptions();
|
||||
this.cleanSession = connectionOptions.isCleanSession();
|
||||
this.consumerStopAction = this.clientFactory.getConsumerStopAction();
|
||||
@@ -259,10 +261,6 @@ public class MqttPahoMessageDrivenChannelAdapter extends AbstractMqttMessageDriv
|
||||
if (this.applicationEventPublisher != null) {
|
||||
this.applicationEventPublisher.publishEvent(new MqttSubscribedEvent(this, message));
|
||||
}
|
||||
// cancel() after the publish in case we are on that thread; a send to a QueueChannel would fail.
|
||||
if (this.reconnectFuture != null) {
|
||||
cancelReconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,19 +273,23 @@ public class MqttPahoMessageDrivenChannelAdapter extends AbstractMqttMessageDriv
|
||||
|
||||
private void scheduleReconnect() {
|
||||
try {
|
||||
this.reconnectFuture = this.getTaskScheduler().scheduleWithFixedDelay(() -> {
|
||||
this.reconnectFuture = getTaskScheduler().schedule(() -> {
|
||||
try {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Attempting reconnect");
|
||||
}
|
||||
if (!MqttPahoMessageDrivenChannelAdapter.this.connected) {
|
||||
connectAndSubscribe();
|
||||
synchronized (MqttPahoMessageDrivenChannelAdapter.this) {
|
||||
if (!MqttPahoMessageDrivenChannelAdapter.this.connected) {
|
||||
connectAndSubscribe();
|
||||
MqttPahoMessageDrivenChannelAdapter.this.reconnectFuture = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MqttException e) {
|
||||
logger.error("Exception while connecting and subscribing", e);
|
||||
scheduleReconnect();
|
||||
}
|
||||
}, this.recoveryInterval);
|
||||
}, new Date(System.currentTimeMillis() + this.recoveryInterval));
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("Failed to schedule reconnect", e);
|
||||
@@ -295,7 +297,7 @@ public class MqttPahoMessageDrivenChannelAdapter extends AbstractMqttMessageDriv
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionLost(Throwable cause) {
|
||||
public synchronized void connectionLost(Throwable cause) {
|
||||
this.logger.error("Lost connection:" + cause.getMessage() + "; retrying...");
|
||||
this.connected = false;
|
||||
scheduleReconnect();
|
||||
|
||||
Reference in New Issue
Block a user