HDFS-17111. RBF: Optimize msync to only call nameservices that have observer reads enabled. (#5860). Contributed by Simbarashe Dzinamarira.

This commit is contained in:
Simbarashe Dzinamarira 2023-07-26 00:52:13 -07:00 committed by GitHub
parent c04a17f116
commit ad001c93cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 5 deletions

View File

@ -1928,9 +1928,17 @@ public BatchedEntries<OpenFileEntry> listOpenFiles(long prevId,
@Override
public void msync() throws IOException {
rpcServer.checkOperation(NameNode.OperationCategory.READ, true);
Set<FederationNamespaceInfo> nss = namenodeResolver.getNamespaces();
// Only msync to nameservices with observer reads enabled.
Set<FederationNamespaceInfo> allNamespaces = namenodeResolver.getNamespaces();
RemoteMethod method = new RemoteMethod("msync");
rpcClient.invokeConcurrent(nss, method);
Set<FederationNamespaceInfo> namespacesEligibleForObserverReads = allNamespaces
.stream()
.filter(ns -> rpcClient.isNamespaceObserverReadEligible(ns.getNameserviceId()))
.collect(Collectors.toSet());
if (namespacesEligibleForObserverReads.isEmpty()) {
return;
}
rpcClient.invokeConcurrent(namespacesEligibleForObserverReads, method);
}
@Override

View File

@ -1783,9 +1783,16 @@ && isNamespaceStateIdFresh(nsId)
}
private boolean isObserverReadEligible(String nsId, Method method) {
boolean isReadEnabledForNamespace =
observerReadEnabledDefault != observerReadEnabledOverrides.contains(nsId);
return isReadEnabledForNamespace && isReadCall(method);
return isReadCall(method) && isNamespaceObserverReadEligible(nsId);
}
/**
* Check if a namespace is eligible for observer reads.
* @param nsId namespaceID
* @return whether the 'namespace' has observer reads enabled.
*/
boolean isNamespaceObserverReadEligible(String nsId) {
return observerReadEnabledDefault != observerReadEnabledOverrides.contains(nsId);
}
/**
@ -1793,6 +1800,9 @@ private boolean isObserverReadEligible(String nsId, Method method) {
* @return whether the 'method' is a read-only operation.
*/
private static boolean isReadCall(Method method) {
if (method == null) {
return false;
}
if (!method.isAnnotationPresent(ReadOnly.class)) {
return false;
}

View File

@ -871,4 +871,45 @@ public void testThatWriteDoesntBypassNeedForMsync(ConfigSetting configSetting) t
Assertions.fail("Unknown config setting: " + configSetting);
}
}
@EnumSource(ConfigSetting.class)
@ParameterizedTest
@Tag(SKIP_BEFORE_EACH_CLUSTER_STARTUP)
public void testMsyncOnlyToNamespaceWithObserver(ConfigSetting configSetting) throws Exception {
Configuration confOverride = new Configuration(false);
String namespaceWithObserverReadsDisabled = "ns0";
// Disable observer reads for ns0
confOverride.set(RBFConfigKeys.DFS_ROUTER_OBSERVER_READ_OVERRIDES,
namespaceWithObserverReadsDisabled);
startUpCluster(1, confOverride);
fileSystem = routerContext.getFileSystem(getConfToEnableObserverReads(configSetting));
// Send msync request
fileSystem.msync();
long rpcCountForActive = routerContext.getRouter().getRpcServer()
.getRPCMetrics().getActiveProxyOps();
// There should only be one call to the namespace that has an observer.
assertEquals("Only one call to the namespace with an observer", 1, rpcCountForActive);
}
@EnumSource(ConfigSetting.class)
@ParameterizedTest
@Tag(SKIP_BEFORE_EACH_CLUSTER_STARTUP)
public void testMsyncWithNoNamespacesEligibleForCRS(ConfigSetting configSetting)
throws Exception {
Configuration confOverride = new Configuration(false);
// Disable observer reads for all namespaces.
confOverride.setBoolean(RBFConfigKeys.DFS_ROUTER_OBSERVER_READ_DEFAULT_KEY, false);
startUpCluster(1, confOverride);
fileSystem = routerContext.getFileSystem(getConfToEnableObserverReads(configSetting));
// Send msync request.
fileSystem.msync();
long rpcCountForActive = routerContext.getRouter().getRpcServer()
.getRPCMetrics().getActiveProxyOps();
// There should no calls to any namespace.
assertEquals("No calls to any namespace", 0, rpcCountForActive);
}
}