diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java index 0b6007d1de4..948082991c7 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java @@ -300,9 +300,9 @@ public class Constants { public static final long LEAST_HEARTBEAT_DURATION = 1000; /** - * ticks per wheel. Currently only contains two tasks, so 16 locations are enough + * ticks per wheel. */ - public static final int TICKS_PER_WHEEL = 16; + public static final int TICKS_PER_WHEEL = 128; public static final String HEARTBEAT_TIMEOUT_KEY = "heartbeat.timeout"; diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/AbstractTimerTask.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/AbstractTimerTask.java index 003af243d86..befa6887806 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/AbstractTimerTask.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/AbstractTimerTask.java @@ -34,6 +34,8 @@ public abstract class AbstractTimerTask implements TimerTask { private final Long tick; + protected volatile boolean cancel = false; + AbstractTimerTask(ChannelProvider channelProvider, Long tick) { if (channelProvider == null || tick == null) { throw new IllegalArgumentException(); @@ -54,11 +56,19 @@ static Long now() { return System.currentTimeMillis(); } + public void cancel() { + this.cancel = true; + } + private void reput(Timeout timeout, Long tick) { if (timeout == null || tick == null) { throw new IllegalArgumentException(); } + if (cancel) { + return; + } + Timer timer = timeout.timer(); if (timer.isStop() || timeout.isCancelled()) { return; diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java index a28d53ec51a..65862b6d6af 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java @@ -43,9 +43,13 @@ public class HeaderExchangeClient implements ExchangeClient { private int heartbeat; private int idleTimeout; - private static HashedWheelTimer idleCheckTimer = new HashedWheelTimer(new NamedThreadFactory("dubbo-client-idleCheck", true), 1, + private static final HashedWheelTimer IDLE_CHECK_TIMER = new HashedWheelTimer(new NamedThreadFactory("dubbo-client-idleCheck", true), 1, TimeUnit.SECONDS, Constants.TICKS_PER_WHEEL); + private HeartbeatTimerTask heartBeatTimerTask; + + private ReconnectTimerTask reconnectTimerTask; + public HeaderExchangeClient(Client client, boolean needHeartbeat) { Assert.notNull(client, "Client can't be null"); this.client = client; @@ -182,12 +186,17 @@ private void startIdleCheckTask() { HeartbeatTimerTask heartBeatTimerTask = new HeartbeatTimerTask(cp, heartbeatTick, heartbeat); ReconnectTimerTask reconnectTimerTask = new ReconnectTimerTask(cp, heartbeatTimeoutTick, idleTimeout); + this.heartBeatTimerTask = heartBeatTimerTask; + this.reconnectTimerTask = reconnectTimerTask; + // init task and start timer. - idleCheckTimer.newTimeout(heartBeatTimerTask, heartbeatTick, TimeUnit.MILLISECONDS); - idleCheckTimer.newTimeout(reconnectTimerTask, heartbeatTimeoutTick, TimeUnit.MILLISECONDS); + IDLE_CHECK_TIMER.newTimeout(heartBeatTimerTask, heartbeatTick, TimeUnit.MILLISECONDS); + IDLE_CHECK_TIMER.newTimeout(reconnectTimerTask, heartbeatTimeoutTick, TimeUnit.MILLISECONDS); } private void doClose() { + heartBeatTimerTask.cancel(); + reconnectTimerTask.cancel(); } /** diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java index 4609d2ab529..65b0836fcc8 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java @@ -53,9 +53,11 @@ public class HeaderExchangeServer implements ExchangeServer { private int idleTimeout; private AtomicBoolean closed = new AtomicBoolean(false); - private static HashedWheelTimer idleCheckTimer = new HashedWheelTimer(new NamedThreadFactory("dubbo-server-idleCheck", true), 1, + private static final HashedWheelTimer IDLE_CHECK_TIMER = new HashedWheelTimer(new NamedThreadFactory("dubbo-server-idleCheck", true), 1, TimeUnit.SECONDS, Constants.TICKS_PER_WHEEL); + private CloseTimerTask closeTimerTask; + public HeaderExchangeServer(Server server) { Assert.notNull(server, "server == null"); this.server = server; @@ -148,6 +150,11 @@ private void doClose() { if (!closed.compareAndSet(false, true)) { return; } + cancelCloseTask(); + } + + private void cancelCloseTask() { + closeTimerTask.cancel(); } @Override @@ -214,6 +221,8 @@ public void reset(URL url) { heartbeat = h; idleTimeout = t; + // we need cancel the exist closeTimeout first. + cancelCloseTask(); startIdleCheckTask(); } } @@ -262,9 +271,10 @@ private void startIdleCheckTask() { long idleTimeoutTick = calculateLeastDuration(idleTimeout); CloseTimerTask closeTimerTask = new CloseTimerTask(cp, idleTimeoutTick, idleTimeout); + this.closeTimerTask = closeTimerTask; // init task and start timer. - idleCheckTimer.newTimeout(closeTimerTask, idleTimeoutTick, TimeUnit.MILLISECONDS); + IDLE_CHECK_TIMER.newTimeout(closeTimerTask, idleTimeoutTick, TimeUnit.MILLISECONDS); } }