-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-26180 Introduce a initial refresh interval for RpcConnectionReg… #3601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,7 @@ final class RegistryEndpointsRefresher { | |
|
||
private final Thread thread; | ||
private final Refresher refresher; | ||
private final long initialDelayMs; | ||
private final long periodicRefreshMs; | ||
private final long minTimeBetweenRefreshesMs; | ||
|
||
|
@@ -56,9 +57,20 @@ synchronized void stop() { | |
notifyAll(); | ||
} | ||
|
||
private long getRefreshIntervalMs(boolean firstRefresh) { | ||
if (refreshNow) { | ||
return minTimeBetweenRefreshesMs; | ||
} | ||
if (firstRefresh) { | ||
return initialDelayMs; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One minor edge case is initialDelayMs > periodicRefreshMs (like in a misconfiguration), that needs to be handled ? (or) we can make initialDelayMs = periodicRefreshMs/4 or something like that, essentially a f(periodicRefreshMs) rather than a separate config, whatever works for you, I don't have a preference. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think a new config option is needed, but the default value could be periodicRefreshMs/4 or /5, if users explicitly set it, we will use the value set by users. WDYT? |
||
} | ||
return periodicRefreshMs; | ||
} | ||
|
||
// The main loop for the refresh thread. | ||
private void mainLoop() { | ||
long lastRefreshTime = EnvironmentEdgeManager.currentTime(); | ||
boolean firstRefresh = true; | ||
for (;;) { | ||
synchronized (this) { | ||
for (;;) { | ||
|
@@ -68,9 +80,12 @@ private void mainLoop() { | |
} | ||
// if refreshNow is true, then we will wait until minTimeBetweenRefreshesMs elapsed, | ||
// otherwise wait until periodicRefreshMs elapsed | ||
long waitTime = (refreshNow ? minTimeBetweenRefreshesMs : periodicRefreshMs) - | ||
long waitTime = getRefreshIntervalMs(firstRefresh) - | ||
(EnvironmentEdgeManager.currentTime() - lastRefreshTime); | ||
if (waitTime <= 0) { | ||
// we are going to refresh, reset this flag | ||
firstRefresh = false; | ||
refreshNow = false; | ||
break; | ||
} | ||
try { | ||
|
@@ -81,8 +96,6 @@ private void mainLoop() { | |
continue; | ||
} | ||
} | ||
// we are going to refresh, reset this flag | ||
refreshNow = false; | ||
} | ||
LOG.debug("Attempting to refresh registry end points"); | ||
try { | ||
|
@@ -104,8 +117,9 @@ public interface Refresher { | |
void refresh() throws IOException; | ||
} | ||
|
||
private RegistryEndpointsRefresher(long periodicRefreshMs, long minTimeBetweenRefreshesMs, | ||
Refresher refresher) { | ||
private RegistryEndpointsRefresher(long initialDelayMs, long periodicRefreshMs, | ||
long minTimeBetweenRefreshesMs, Refresher refresher) { | ||
this.initialDelayMs = initialDelayMs; | ||
this.periodicRefreshMs = periodicRefreshMs; | ||
this.minTimeBetweenRefreshesMs = minTimeBetweenRefreshesMs; | ||
this.refresher = refresher; | ||
|
@@ -129,16 +143,19 @@ synchronized void refreshNow() { | |
* {@code intervalSecsConfigName} is less than zero, will return null here, which means disable | ||
* refreshing of endpoints. | ||
*/ | ||
static RegistryEndpointsRefresher create(Configuration conf, String intervalSecsConfigName, | ||
String minIntervalSecsConfigName, Refresher refresher) { | ||
static RegistryEndpointsRefresher create(Configuration conf, String initialDelaySecsConfigName, | ||
String intervalSecsConfigName, String minIntervalSecsConfigName, Refresher refresher) { | ||
long periodicRefreshMs = TimeUnit.SECONDS | ||
.toMillis(conf.getLong(intervalSecsConfigName, PERIODIC_REFRESH_INTERVAL_SECS_DEFAULT)); | ||
if (periodicRefreshMs <= 0) { | ||
return null; | ||
} | ||
long initialDelayMs = Math.max(1, | ||
TimeUnit.SECONDS.toMillis(conf.getLong(initialDelaySecsConfigName, periodicRefreshMs / 10))); | ||
long minTimeBetweenRefreshesMs = TimeUnit.SECONDS | ||
.toMillis(conf.getLong(minIntervalSecsConfigName, MIN_SECS_BETWEEN_REFRESHES_DEFAULT)); | ||
Preconditions.checkArgument(minTimeBetweenRefreshesMs < periodicRefreshMs); | ||
return new RegistryEndpointsRefresher(periodicRefreshMs, minTimeBetweenRefreshesMs, refresher); | ||
return new RegistryEndpointsRefresher(initialDelayMs, periodicRefreshMs, | ||
minTimeBetweenRefreshesMs, refresher); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this works ok for a large cluster once we populate the stubs of all the bootstrap nodes. But for a smaller cluster (<=10), populateStubs() returns everything. So its likely that even after the first refresh, all the subsequent refreshes hit the same bunch of nodes at the same time.
It looks to me like the right way to fix this is to add jitter to the refreshTime? jitter is a random sleep between (0, n) so that we spread out the calls, this is for all the refreshes and not just the first refresh, WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think jitter is used to solve another problem? It is always good to add a jitter to periodically requests to reduce the possibility to request at the same time.
For the purpose of this issue, let me just paste the description here first to see it can help you to understand better
Free feel to ask if you have other concerns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sorry interpreted it as something else totally. I thought you were talking about what if all requests hit the servers at the same time and suggested jitter, my bad!