概述
訪問HDFS其實很簡單
這裏記錄一些方法,具備下面的特徵:
- 通過租戶代理訪問 Kerberos 認證的 HADOOP 資源
- 獲取 FileSystem 對象的技巧:FileSystem.get(URI, configuration)
- 通用 doAs模板
- 通用 hdfsCommand模板,使用 try-with-resources。
- 截取 hdfs://namenode/user/...,使得 namenode對應得 FileSystem 能夠緩存。
- FileSystem.getDefaultUri(...) 如果使用這個方法,則路徑必須以core-site.xml得 fs.defaultFs 爲開頭。會出現錯誤 Wrong FS: hdfs://dc1, expected: viewfs://ssss。
- 通過指定 FileSystem.get() 第一個參數,能保證和實際得 namenode 一致。
- 因此能同時訪問 hdfs://或者viewfs://。
通用代理
public static <T> T doAs(Supplier<T> command, String clusterName) {
return UserGroupInformation.createProxyUser(clusterName, SecureYarn.ugi).doAs((PrivilegedAction<T>) command::get);
}
public static URI getFsUri(String filePath) {
URI fsUri;
if (filePath.startsWith("hdfs://")) {
String uri = filePath.substring(0, filePath.indexOf("/user"));
fsUri = new Path(uri).toUri();
} else {
fsUri = null;
}
return fsUri;
}
listFiles 和 hdfsCommand 模板
public static FileStatus[] listFiles(String filePath, String clusterName, Configuration configuration) {
return doAs(() -> hdfsCommand(c -> c.listStatus(new Path(filePath)), getFsUri(filePath), configuration), clusterName);
}
public static <V> V hdfsCommand(ThrowingFunction<FileSystem, V, Exception> command, URI path, Configuration hdfsConfig) {
try (FileSystem fileSystem = FileSystem.get(path == null ? FileSystem.getDefaultUri(hdfsConfig):path, hdfsConfig)) {
return command.apply(fileSystem);
} catch (Exception e) {
throw new RuntimeException(e);
}
}