This is an automated email from the ASF dual-hosted git repository. dragonyliu pushed a commit to branch branch-2 in repository https://gitbox.apache.org/repos/asf/ratis.git
commit 87d7d0144ed0d059afa824d44d96d65e0b01075e Author: William Song <[email protected]> AuthorDate: Fri Aug 19 23:18:29 2022 +0800 RATIS-1638. Separate first election timeout (#713) (cherry picked from commit e49687aba20cad70c576900f1be59bb8fcd55d10) --- .../main/java/org/apache/ratis/conf/ConfUtils.java | 14 +++++++- .../apache/ratis/server/RaftServerConfigKeys.java | 39 +++++++++++++++++++--- .../apache/ratis/server/impl/RaftServerImpl.java | 17 ++++++++++ .../org/apache/ratis/server/impl/ServerState.java | 1 + 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java b/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java index 681c0dc67..629d5a389 100644 --- a/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java +++ b/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java @@ -214,6 +214,17 @@ public interface ConfUtils { return value; } + @SafeVarargs + static TimeDuration getTimeDuration( + BiFunction<String, TimeDuration, TimeDuration> getter, + String key, TimeDuration defaultValue, String fallbackKey, TimeDuration fallbackValue, + Consumer<String> logger, BiConsumer<String, TimeDuration>... assertions) { + final TimeDuration value = get(getter, key, defaultValue, fallbackKey, fallbackValue, logger, assertions); + requireNonNegativeTimeDuration().accept(key, value); + return value; + } + + static TlsConf getTlsConf( Function<String, TlsConf> tlsConfGetter, String key, Consumer<String> logger) { @@ -236,10 +247,11 @@ public interface ConfUtils { T value = get(getter, key, defaultValue, null, assertions); if (value != defaultValue) { logGet(key, value, defaultValue, logger); + return value; } else { logFallback(key, fallbackKey, fallbackValue, logger); + return fallbackValue; } - return value; } static InetSocketAddress getInetSocketAddress( diff --git a/ratis-server-api/src/main/java/org/apache/ratis/server/RaftServerConfigKeys.java b/ratis-server-api/src/main/java/org/apache/ratis/server/RaftServerConfigKeys.java index 6d0c5d41b..e24631378 100644 --- a/ratis-server-api/src/main/java/org/apache/ratis/server/RaftServerConfigKeys.java +++ b/ratis-server-api/src/main/java/org/apache/ratis/server/RaftServerConfigKeys.java @@ -619,9 +619,12 @@ public interface RaftServerConfigKeys { String TIMEOUT_MIN_KEY = PREFIX + ".timeout.min"; TimeDuration TIMEOUT_MIN_DEFAULT = TimeDuration.valueOf(150, TimeUnit.MILLISECONDS); - static TimeDuration timeoutMin(RaftProperties properties) { + static TimeDuration timeoutMin(RaftProperties properties, Consumer<String> logger) { return getTimeDuration(properties.getTimeDuration(TIMEOUT_MIN_DEFAULT.getUnit()), - TIMEOUT_MIN_KEY, TIMEOUT_MIN_DEFAULT, getDefaultLog()); + TIMEOUT_MIN_KEY, TIMEOUT_MIN_DEFAULT, logger); + } + static TimeDuration timeoutMin(RaftProperties properties) { + return timeoutMin(properties, getDefaultLog()); } static void setTimeoutMin(RaftProperties properties, TimeDuration minDuration) { setTimeDuration(properties::setTimeDuration, TIMEOUT_MIN_KEY, minDuration); @@ -629,14 +632,42 @@ public interface RaftServerConfigKeys { String TIMEOUT_MAX_KEY = PREFIX + ".timeout.max"; TimeDuration TIMEOUT_MAX_DEFAULT = TimeDuration.valueOf(300, TimeUnit.MILLISECONDS); - static TimeDuration timeoutMax(RaftProperties properties) { + static TimeDuration timeoutMax(RaftProperties properties, Consumer<String> logger) { return getTimeDuration(properties.getTimeDuration(TIMEOUT_MAX_DEFAULT.getUnit()), - TIMEOUT_MAX_KEY, TIMEOUT_MAX_DEFAULT, getDefaultLog()); + TIMEOUT_MAX_KEY, TIMEOUT_MAX_DEFAULT, logger); + } + static TimeDuration timeoutMax(RaftProperties properties) { + return timeoutMax(properties, getDefaultLog()); } static void setTimeoutMax(RaftProperties properties, TimeDuration maxDuration) { setTimeDuration(properties::setTimeDuration, TIMEOUT_MAX_KEY, maxDuration); } + /** separate first timeout so that the startup unavailable time can be reduced */ + String FIRST_ELECTION_TIMEOUT_MIN_KEY = PREFIX + ".first-election.timeout.min"; + TimeDuration FIRST_ELECTION_TIMEOUT_MIN_DEFAULT = null; + static TimeDuration firstElectionTimeoutMin(RaftProperties properties) { + final TimeDuration fallbackFirstElectionTimeoutMin = Rpc.timeoutMin(properties, null); + return getTimeDuration(properties.getTimeDuration(fallbackFirstElectionTimeoutMin.getUnit()), + FIRST_ELECTION_TIMEOUT_MIN_KEY, FIRST_ELECTION_TIMEOUT_MIN_DEFAULT, + Rpc.TIMEOUT_MIN_KEY, fallbackFirstElectionTimeoutMin, getDefaultLog()); + } + static void setFirstElectionTimeoutMin(RaftProperties properties, TimeDuration firstMinDuration) { + setTimeDuration(properties::setTimeDuration, FIRST_ELECTION_TIMEOUT_MIN_KEY, firstMinDuration); + } + + String FIRST_ELECTION_TIMEOUT_MAX_KEY = PREFIX + ".first-election.timeout.max"; + TimeDuration FIRST_ELECTION_TIMEOUT_MAX_DEFAULT = null; + static TimeDuration firstElectionTimeoutMax(RaftProperties properties) { + final TimeDuration fallbackFirstElectionTimeoutMax = Rpc.timeoutMax(properties, null); + return getTimeDuration(properties.getTimeDuration(fallbackFirstElectionTimeoutMax.getUnit()), + FIRST_ELECTION_TIMEOUT_MAX_KEY, FIRST_ELECTION_TIMEOUT_MAX_DEFAULT, + Rpc.TIMEOUT_MAX_KEY, fallbackFirstElectionTimeoutMax, getDefaultLog()); + } + static void setFirstElectionTimeoutMax(RaftProperties properties, TimeDuration firstMaxDuration) { + setTimeDuration(properties::setTimeDuration, FIRST_ELECTION_TIMEOUT_MAX_KEY, firstMaxDuration); + } + String REQUEST_TIMEOUT_KEY = PREFIX + ".request.timeout"; TimeDuration REQUEST_TIMEOUT_DEFAULT = TimeDuration.valueOf(3000, TimeUnit.MILLISECONDS); static TimeDuration requestTimeout(RaftProperties properties) { diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java index ee314dbe2..1994fa8de 100644 --- a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java +++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java @@ -187,6 +187,8 @@ class RaftServerImpl implements RaftServer.Division, private final ExecutorService serverExecutor; private final ExecutorService clientExecutor; + private final AtomicBoolean firstElectionSinceStartup = new AtomicBoolean(true); + RaftServerImpl(RaftGroup group, StateMachine stateMachine, RaftServerProxy proxy) throws IOException { final RaftPeerId id = proxy.getId(); LOG.info("{}: new RaftServerImpl for {} with {}", id, group, stateMachine); @@ -245,11 +247,22 @@ class RaftServerImpl implements RaftServer.Division, } TimeDuration getRandomElectionTimeout() { + if (firstElectionSinceStartup.get()) { + return getFirstRandomElectionTimeout(); + } final int min = properties().minRpcTimeoutMs(); final int millis = min + ThreadLocalRandom.current().nextInt(properties().maxRpcTimeoutMs() - min + 1); return TimeDuration.valueOf(millis, TimeUnit.MILLISECONDS); } + private TimeDuration getFirstRandomElectionTimeout() { + final RaftProperties properties = proxy.getProperties(); + final int min = RaftServerConfigKeys.Rpc.firstElectionTimeoutMin(properties).toIntExact(TimeUnit.MILLISECONDS); + final int max = RaftServerConfigKeys.Rpc.firstElectionTimeoutMax(properties).toIntExact(TimeUnit.MILLISECONDS); + final int mills = min + ThreadLocalRandom.current().nextInt(max - min + 1); + return TimeDuration.valueOf(mills, TimeUnit.MILLISECONDS); + } + TimeDuration getLeaderStepDownWaitTime() { return leaderStepDownWaitTime; } @@ -1725,4 +1738,8 @@ class RaftServerImpl implements RaftServer.Division, .collect(Collectors.toList()); } } + + void onGroupLeaderElected() { + this.firstElectionSinceStartup.set(false); + } } diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerState.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerState.java index 34e9cb92c..1ee2cab5e 100644 --- a/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerState.java +++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerState.java @@ -315,6 +315,7 @@ class ServerState implements Closeable { leaderId = newLeaderId; if (leaderId != null) { server.finishTransferLeadership(); + server.onGroupLeaderElected(); } } }
