-
Notifications
You must be signed in to change notification settings - Fork 9.2k
HDFS-16283. RBF: reducing the load of renewLease() RPC #4524
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 1 commit
802a405
de5120f
2d6e01e
642f920
86ad891
6739c22
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 |
|---|---|---|
|
|
@@ -41,6 +41,7 @@ | |
| import java.util.ArrayList; | ||
| import java.util.EnumSet; | ||
| import java.util.HashMap; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Random; | ||
|
|
@@ -188,6 +189,7 @@ | |
| import org.apache.hadoop.util.DataChecksum.Type; | ||
| import org.apache.hadoop.util.Lists; | ||
| import org.apache.hadoop.util.Progressable; | ||
| import org.apache.hadoop.util.StringUtils; | ||
| import org.apache.hadoop.util.Time; | ||
| import org.apache.hadoop.tracing.TraceScope; | ||
| import org.apache.hadoop.tracing.Tracer; | ||
|
|
@@ -579,6 +581,28 @@ void updateLastLeaseRenewal() { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Get all nsIdentifies of DFSOutputStreams. | ||
| */ | ||
| private String getRenewLeaseNSIdentifies() { | ||
| HashSet<String> allNSIdentifies = new HashSet<>(); | ||
| synchronized (filesBeingWritten) { | ||
| if (filesBeingWritten.isEmpty()) { | ||
| return null; | ||
| } | ||
| for (DFSOutputStream outputStream : filesBeingWritten.values()) { | ||
| String nsIdentify = outputStream.getNsIdentify(); | ||
| if (nsIdentify != null && !nsIdentify.isEmpty()) { | ||
| allNSIdentifies.add(nsIdentify); | ||
|
Member
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. In which case it can be One which I can think of is if the router is at older version than the client, means if Router doesn't have this and client is upgraded. I think that scenario should be sorted, if either of the identifier is |
||
| } | ||
| } | ||
| if (allNSIdentifies.isEmpty()) { | ||
| return null; | ||
| } | ||
| } | ||
| return StringUtils.join(",", allNSIdentifies); | ||
| } | ||
|
|
||
| /** | ||
| * Renew leases. | ||
| * @return true if lease was renewed. May return false if this | ||
|
|
@@ -587,7 +611,7 @@ void updateLastLeaseRenewal() { | |
| public boolean renewLease() throws IOException { | ||
| if (clientRunning && !isFilesBeingWrittenEmpty()) { | ||
| try { | ||
| namenode.renewLease(clientName); | ||
| namenode.renewLease(clientName, getRenewLeaseNSIdentifies()); | ||
| updateLastLeaseRenewal(); | ||
| return true; | ||
| } catch (IOException e) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -763,7 +763,7 @@ SnapshotStatus[] getSnapshotListing(String snapshotRoot) | |
| * @throws IOException If an I/O error occurred | ||
| */ | ||
| @Idempotent | ||
| void renewLease(String clientName) throws IOException; | ||
| void renewLease(String clientName, String allNSIdentifies) throws IOException; | ||
|
Member
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. Add detail about the new argument in the javadoc as well |
||
|
|
||
| /** | ||
| * Start lease recovery. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -114,6 +114,7 @@ | |
| import java.util.Map; | ||
| import java.util.Set; | ||
| import java.util.TreeMap; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.TimeUnit; | ||
|
|
||
| /** | ||
|
|
@@ -129,6 +130,8 @@ public class RouterClientProtocol implements ClientProtocol { | |
| private final RouterFederationRename rbfRename; | ||
| private final FileSubclusterResolver subclusterResolver; | ||
| private final ActiveNamenodeResolver namenodeResolver; | ||
| private final Map<String, FederationNamespaceInfo> nsNameSpaceInfoCache | ||
| = new ConcurrentHashMap<>(); | ||
|
|
||
| /** | ||
| * Caching server defaults so as to prevent redundant calls to namenode, | ||
|
|
@@ -291,8 +294,10 @@ public HdfsFileStatus create(String src, FsPermission masked, | |
| RemoteLocation createLocation = null; | ||
| try { | ||
| createLocation = rpcServer.getCreateLocation(src, locations); | ||
| return rpcClient.invokeSingle(createLocation, method, | ||
| HdfsFileStatus status = rpcClient.invokeSingle(createLocation, method, | ||
| HdfsFileStatus.class); | ||
| status.setNsIdentify(createLocation.getNameserviceId()); | ||
| return status; | ||
| } catch (IOException ioe) { | ||
| final List<RemoteLocation> newLocations = checkFaultTolerantRetry( | ||
| method, src, ioe, createLocation, locations); | ||
|
|
@@ -759,14 +764,47 @@ public boolean mkdirs(String src, FsPermission masked, boolean createParent) | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Try to get a list of FederationNamespaceInfo for renewLease RPC. | ||
| */ | ||
| private List<FederationNamespaceInfo> getRewLeaseNSs(String nsIdentifies) | ||
| throws IOException { | ||
| // return all namespaces | ||
| if (nsIdentifies == null || nsIdentifies.isEmpty()) { | ||
| return new ArrayList<>(namenodeResolver.getNamespaces()); | ||
| } | ||
| String[] nsIdList = nsIdentifies.split(","); | ||
|
Member
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. First at client we are doing a String.Joinner stuff, then here we are splitting, can't we pass an array/set/list whichever possible and get rid of this join & split overhead during the call? |
||
| List<FederationNamespaceInfo> result = new ArrayList<>(); | ||
| for (String nsId : nsIdList) { | ||
| FederationNamespaceInfo namespaceInfo = nsNameSpaceInfoCache.get(nsId); | ||
| if (namespaceInfo == null) { | ||
| try { | ||
| rpcClient.getNamenodesForNameservice(nsId); | ||
|
Member
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. What are you doing with the return value? |
||
| } catch (IOException ioe) { | ||
| // return all namespaces when parsing nsId failed. | ||
| return new ArrayList<>(namenodeResolver.getNamespaces()); | ||
|
Member
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. Have some log line here,= |
||
| } | ||
| namespaceInfo = new FederationNamespaceInfo("", "", nsId); | ||
| nsNameSpaceInfoCache.put(nsId, namespaceInfo); | ||
|
Member
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 didn't catch this logic of new |
||
| } | ||
| result.add(namespaceInfo); | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| @Override | ||
| public void renewLease(String clientName) throws IOException { | ||
| public void renewLease(String clientName, String nsIdentifies) | ||
| throws IOException { | ||
| rpcServer.checkOperation(NameNode.OperationCategory.WRITE); | ||
|
|
||
| RemoteMethod method = new RemoteMethod("renewLease", | ||
| new Class<?>[] {String.class}, clientName); | ||
| Set<FederationNamespaceInfo> nss = namenodeResolver.getNamespaces(); | ||
| rpcClient.invokeConcurrent(nss, method, false, false); | ||
| new Class<?>[] {String.class, String.class}, clientName, null); | ||
| List<FederationNamespaceInfo> nss = getRewLeaseNSs(nsIdentifies); | ||
| if (nss.size() == 1) { | ||
| rpcClient.invokeSingle(nss.get(0).getNameserviceId(), method); | ||
|
Comment on lines
+805
to
+806
Member
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. nsId is getting passed from the client, if we get an array or so, you can figure out initially itself whether you have only one entry or not. so you can get rid of |
||
| } else { | ||
| rpcClient.invokeConcurrent(nss, method, false, false); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
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.
Identifies in the method names and arguments, doesn't make sense, Can we change it to
NsIndentifiers, well I am good with justnamespaces/namespacealso