Support config close timeout (#12386)

* Support config close timeout

* Fix spell

* fix ut
This commit is contained in:
Albumen Kevin 2023-05-23 14:52:49 +08:00 committed by GitHub
parent 5641c431fd
commit e5d2a5798e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 17 deletions

View File

@ -144,8 +144,10 @@ public interface Constants {
String TELNET_KEY = "telnet";
String HEARTBEAT_KEY = "heartbeat";
String HEARTBEAT_CONFIG_KEY = "dubbo.protocol.default-heartbeat";
String CLOSE_TIMEOUT_CONFIG_KEY = "dubbo.protocol.default-close-timeout";
int DEFAULT_HEARTBEAT = 60 * 1000;
String HEARTBEAT_TIMEOUT_KEY = "heartbeat.timeout";
String CLOSE_TIMEOUT_KEY = "close.timeout";
String CONNECTIONS_KEY = "connections";
int DEFAULT_BACKLOG = 1024;

View File

@ -32,11 +32,11 @@ public class CloseTimerTask extends AbstractTimerTask {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(CloseTimerTask.class);
private final int idleTimeout;
private final int closeTimeout;
public CloseTimerTask(ChannelProvider channelProvider, HashedWheelTimer hashedWheelTimer, Long heartbeatTimeoutTick, int idleTimeout) {
super(channelProvider, hashedWheelTimer, heartbeatTimeoutTick);
this.idleTimeout = idleTimeout;
public CloseTimerTask(ChannelProvider channelProvider, HashedWheelTimer hashedWheelTimer, Long tick, int closeTimeout) {
super(channelProvider, hashedWheelTimer, tick);
this.closeTimeout = closeTimeout;
}
@Override
@ -46,9 +46,9 @@ public class CloseTimerTask extends AbstractTimerTask {
Long lastWrite = lastWrite(channel);
Long now = now();
// check ping & pong at server
if ((lastRead != null && now - lastRead > idleTimeout)
|| (lastWrite != null && now - lastWrite > idleTimeout)) {
logger.warn(PROTOCOL_FAILED_RESPONSE, "", "", "Close channel " + channel + ", because idleCheck timeout: " + idleTimeout + "ms");
if ((lastRead != null && now - lastRead > closeTimeout)
|| (lastWrite != null && now - lastWrite > closeTimeout)) {
logger.warn(PROTOCOL_FAILED_RESPONSE, "", "", "Close channel " + channel + ", because idleCheck timeout: " + closeTimeout + "ms");
channel.close();
}
} catch (Throwable t) {

View File

@ -49,8 +49,7 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.TRANSPORT_FA
import static org.apache.dubbo.remoting.Constants.HEARTBEAT_CHECK_TICK;
import static org.apache.dubbo.remoting.Constants.LEAST_HEARTBEAT_DURATION;
import static org.apache.dubbo.remoting.Constants.TICKS_PER_WHEEL;
import static org.apache.dubbo.remoting.utils.UrlUtils.getHeartbeat;
import static org.apache.dubbo.remoting.utils.UrlUtils.getIdleTimeout;
import static org.apache.dubbo.remoting.utils.UrlUtils.getCloseTimeout;
/**
* ExchangeServerImpl
@ -211,11 +210,9 @@ public class HeaderExchangeServer implements ExchangeServer {
public void reset(URL url) {
server.reset(url);
try {
int currHeartbeat = getHeartbeat(getUrl());
int currIdleTimeout = getIdleTimeout(getUrl());
int heartbeat = getHeartbeat(url);
int idleTimeout = getIdleTimeout(url);
if (currHeartbeat != heartbeat || currIdleTimeout != idleTimeout) {
int currCloseTimeout = getCloseTimeout(getUrl());
int closeTimeout = getCloseTimeout(url);
if (closeTimeout != currCloseTimeout) {
cancelCloseTask();
startIdleCheckTask(url);
}
@ -262,9 +259,9 @@ public class HeaderExchangeServer implements ExchangeServer {
private void startIdleCheckTask(URL url) {
if (!server.canHandleIdle()) {
AbstractTimerTask.ChannelProvider cp = () -> unmodifiableCollection(HeaderExchangeServer.this.getChannels());
int idleTimeout = getIdleTimeout(url);
long idleTimeoutTick = calculateLeastDuration(idleTimeout);
this.closeTimer = new CloseTimerTask(cp, IDLE_CHECK_TIMER.get(), idleTimeoutTick, idleTimeout);
int closeTimeout = getCloseTimeout(url);
long closeTimeoutTick = calculateLeastDuration(closeTimeout);
this.closeTimer = new CloseTimerTask(cp, IDLE_CHECK_TIMER.get(), closeTimeoutTick, closeTimeout);
}
}
}

View File

@ -36,6 +36,27 @@ import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY;
public class UrlUtils {
private static final String ALLOWED_SERIALIZATION_KEY = "allowedSerialization";
public static int getCloseTimeout(URL url) {
String configuredCloseTimeout = System.getProperty(Constants.CLOSE_TIMEOUT_CONFIG_KEY);
int defaultCloseTimeout = -1;
if (StringUtils.isNotEmpty(configuredCloseTimeout)) {
try {
defaultCloseTimeout = Integer.parseInt(configuredCloseTimeout);
} catch (NumberFormatException e) {
// use default heartbeat
}
}
if (defaultCloseTimeout < 0) {
defaultCloseTimeout = getIdleTimeout(url);
}
int closeTimeout = url.getParameter(Constants.CLOSE_TIMEOUT_KEY, defaultCloseTimeout);
int heartbeat = getHeartbeat(url);
if (closeTimeout < heartbeat * 2) {
throw new IllegalStateException("closeTimeout < heartbeatInterval * 2");
}
return closeTimeout;
}
public static int getIdleTimeout(URL url) {
int heartBeat = getHeartbeat(url);
// idleTimeout should be at least more than twice heartBeat because possible retries of client.

View File

@ -46,4 +46,28 @@ class UrlUtilsTest {
Assertions.assertEquals(200, UrlUtils.getHeartbeat(url));
System.clearProperty(Constants.HEARTBEAT_CONFIG_KEY);
}
@Test
void testGetCloseTimeout() {
URL url1 = URL.valueOf("dubbo://127.0.0.1:12345?heartbeat=10000");
URL url2 = URL.valueOf("dubbo://127.0.0.1:12345?heartbeat=10000&heartbeat.timeout=50000");
URL url3 = URL.valueOf("dubbo://127.0.0.1:12345?heartbeat=10000&heartbeat.timeout=10000");
URL url4 = URL.valueOf("dubbo://127.0.0.1:12345?close.timeout=30000&heartbeat=10000&heartbeat.timeout=10000");
URL url5 = URL.valueOf("dubbo://127.0.0.1:12345?close.timeout=40000&heartbeat=10000&heartbeat.timeout=50000");
URL url6 = URL.valueOf("dubbo://127.0.0.1:12345?close.timeout=10000&heartbeat=10000&heartbeat.timeout=10000");
Assertions.assertEquals(30000, UrlUtils.getCloseTimeout(url1));
Assertions.assertEquals(50000, UrlUtils.getCloseTimeout(url2));
Assertions.assertThrows(RuntimeException.class, () -> UrlUtils.getCloseTimeout(url3));
Assertions.assertThrows(RuntimeException.class, () -> UrlUtils.getCloseTimeout(url4));
Assertions.assertEquals(40000, UrlUtils.getCloseTimeout(url5));
Assertions.assertThrows(RuntimeException.class, () -> UrlUtils.getCloseTimeout(url6));
}
@Test
void testConfiguredClose() {
System.setProperty(Constants.CLOSE_TIMEOUT_CONFIG_KEY, "180000");
URL url = URL.valueOf("dubbo://127.0.0.1:12345");
Assertions.assertEquals(180000, UrlUtils.getCloseTimeout(url));
System.clearProperty(Constants.HEARTBEAT_CONFIG_KEY);
}
}